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 t

⟦3564fae00⟧ TextFile

    Length: 16494 (0x406e)
    Types: TextFile
    Names: »tsapd.c«

Derivation

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

TextFile

/* tsapd.c - OSI transport server */

#ifndef	lint
static char *rcsid = "$Header: /f/osi/support/RCS/tsapd.c,v 7.0 89/11/23 22:27:46 mrose Rel $";
#endif

/* 
 * $Header: /f/osi/support/RCS/tsapd.c,v 7.0 89/11/23 22:27:46 mrose Rel $
 *
 *
 * $Log:	tsapd.c,v $
 * Revision 7.0  89/11/23  22:27:46  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 <errno.h>
#include <signal.h>
#include <stdio.h>
#include <varargs.h>
#include "manifest.h"
#include <sys/ioctl.h>
#include <sys/stat.h>
#ifdef	BSD42
#include <sys/file.h>
#endif
#ifdef	SYS5
#include <fcntl.h>
#endif
#ifndef	X_OK
#define	X_OK	1
#endif

#ifndef	NOGOSIP
#include "rosap.h"
#include "rtsap.h"
#include "psap2.h"
#include "ssap.h"
#endif
#include "tpkt.h"

#ifdef	TCP
#include "internet.h"
#endif
#ifdef	X25
#include "x25.h"
#endif
#ifdef	TP4
#include "tp4.h"
#endif
#include "isoservent.h"
#include "tailor.h"

/* \f

 */

static int  debug = 0;
static int  nbits = FD_SETSIZE;

static LLog _pgm_log = {
    "tsapd.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE,
    LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK
};
LLog *pgm_log = &_pgm_log;

static char *myname = "tsapd";
static char myhost[BUFSIZ];

static int	tcpservice = 1;
static int	x25service = 1;
static int	bridgeservice = 1;
static int	tp4service = 1;


#define	NTADDRS	FD_SETSIZE

static struct TSAPaddr *tz;
static struct TSAPaddr  tas[NTADDRS];




void	adios (), advise ();
void	ts_advise ();

#ifdef	NOGOSIP
#define	ssapd	NULLIFP
#else
int	ssapd (), psapd ();
#endif



extern int  errno;

/* \f

 */

/* ARGSUSED */

main (argc, argv, envp)
int     argc;
char  **argv,
      **envp;
{
    int	    failed,
	    listening,
	    vecp;
    char   *vec[4];
    register struct NSAPaddr  *na;
    register struct TSAPaddr  *ta;
    struct TSAPdisconnect   tds;
    register struct TSAPdisconnect  *td = &tds;

    arginit (argv);
    envinit ();

    failed = listening = 0;

    for (ta = tas; ta < tz; ta++) {
	if (ta -> ta_naddr == 0) {
	    if (!tp4service)
		continue;
	}
	else {
	    na = ta -> ta_addrs;
	    
	    switch (na -> na_type) {
	        case NA_TCP:
		    if (!tcpservice)
			continue;
		    break;

		case NA_X25:
		    if (!x25service)
			continue;
		    break;

		case NA_BRG:
		    if (!bridgeservice)
			continue;
		    break;

	        case NA_NSAP:
		    if (!tp4service)
			continue;
		    break;

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

	advise (LLOG_NOTICE, NULLCP, "listening on %s", taddr2str (ta));

	if (TNetListen (ta, td) == NOTOK) {
	    ts_advise (td, LLOG_EXCEPTIONS, "listen failed");
	    failed++;
	}
	else
	    listening++;
    }

    if (!listening)
	adios (NULLCP, failed ? "no successful listens"
			      : "no network services selected");

    for (;;) {
	if (TNetAccept (&vecp, vec, 0, NULLFD, NULLFD, NULLFD, NOTOK, td)
		== NOTOK) {
	    ts_advise (td, LLOG_EXCEPTIONS, "TNetAccept failed");
	    continue;
	}

	if (vecp <= 0)
	    continue;

	switch (TNetFork (vecp, vec, td)) {
	    case OK:
		tsapd (vecp, vec);
		exit (1);
		/* NOTREACHED */

	    case NOTOK:
		ts_advise (td, LLOG_EXCEPTIONS, "fork failed");
	    default:
		break;
	}
    }
}

/* \f

 */

static char buffer1[4096];
static char buffer2[32768];


static int  tsapd (vecp, vec)
int	vecp;
char  **vec;
{
    char    buffer[BUFSIZ];
    register struct isoservent *is;
    struct tsapblk *tb;
    struct TSAPstart   tss;
    register struct TSAPstart *ts = &tss;
    struct TSAPdisconnect   tds;
    register struct TSAPdisconnect  *td = &tds;
    IFP	    hook;

/* begin UGLY */
    (void) strcpy (buffer1, vec[1]);
    (void) strcpy (buffer2, vec[2]);
/* end UGLY */

    if (TInit (vecp, vec, ts, td) == NOTOK) {
	ts_advise (td, LLOG_EXCEPTIONS, "T-CONNECT.INDICATION");
	return;
    }

/* used to print this in ssapd()... */
    advise (LLOG_NOTICE, NULLCP,
	    "T-CONNECT.INDICATION: <%d, %s, %s, %d, %d>",
	    ts -> ts_sd,
	    taddr2str (&ts -> ts_calling), taddr2str (&ts -> ts_called),
	    ts -> ts_expedited, ts -> ts_tsdusize);


    hook = ssapd;
    if (ts -> ts_called.ta_selectlen) {
	if ((is = getisoserventbyselector ("tsap", ts -> ts_called.ta_selector,
					   ts -> ts_called.ta_selectlen))
		== NULL) {
	    (void) sprintf (buffer, "OSI service tsap/%s not found",
			    sel2str (ts -> ts_called.ta_selector,
				     ts -> ts_called.ta_selectlen, 1));
	    goto out;
	}
    }
    else
	if (hook == NULLIFP
	        || (is = getisoserventbyname ("session", "tsap")) == NULL) {
	    (void) strcpy (buffer, "default session service not found");
	    goto out;
	}

    *is -> is_tail++ = buffer1;
    *is -> is_tail++ = buffer2;
    *is -> is_tail = NULL;

    if (tb = findtblk (ts -> ts_sd))
	tb -> tb_fd = NOTOK;
    switch (hook ? (*hook) (is, td) : OK) {
	case NOTOK:
	    ts_advise (td, LLOG_EXCEPTIONS, "service not started at tsap");
	case DONE:
	    exit (1);
	    /* NOTREACHED */

	case OK:
	default:
	    (void) setperms (is);
	    (void) execv (*is -> is_vec, is -> is_vec);
	    (void) sprintf (buffer, "unable to exec %s: %s",
			    *is -> is_vec, sys_errname (errno));
	    SLOG (pgm_log, LLOG_FATAL, NULLCP, ("%s", buffer));
	    break;
    }

out: ;
    advise (LLOG_EXCEPTIONS, NULLCP, "%s", buffer);
    if (strlen (buffer) >= TD_SIZE)
	buffer[0] = NULL;
    (void) TDiscRequest (ts -> ts_sd, buffer, strlen (buffer) + 1, td);

    exit (1);
}

/* \f

 */

static int  setperms (is)
register struct isoservent *is;
{
    struct stat st;

    if (stat (*is -> is_vec, &st) == NOTOK) {
	(void) setgid (1);
	(void) setuid (1);
    }
    else {
	(void) setgid (st.st_gid);
	(void) setuid (st.st_uid);
    }
}

/* \f

 */

static void  ts_advise (td, code, event)
register struct TSAPdisconnect *td;
int	code;
char   *event;
{
    char    buffer[BUFSIZ];

    if (td -> td_cc > 0)
	(void) sprintf (buffer, "[%s] %*.*s",
		TErrString (td -> td_reason),
		td -> td_cc, td -> td_cc, td -> td_data);
    else
	(void) sprintf (buffer, "[%s]", TErrString (td -> td_reason));

    advise (code, NULLCP, "%s: %s", event, buffer);
}

/* \f

 */

#ifndef	NOGOSIP
static int  ssapd (is, td)
register struct isoservent *is;
register struct TSAPdisconnect *td;
{
    int	    sd;
    struct TSAPstart    tss;
    register struct TSAPstart  *ts = &tss;
    struct SSAPindication sis;
    register struct SSAPabort *sa = &sis.si_abort;

    if (strcmp (is -> is_entity, "session")
	    || strcmp (is -> is_provider, "tsap"))
	return OK;

    if (TInit (is -> is_tail - is -> is_vec, is -> is_vec, ts, td) == NOTOK)
	return NOTOK;

    sd = ts -> ts_sd;

    if (TConnResponse (sd, &ts -> ts_called, ts -> ts_expedited, NULLCP, 0,
		       NULLQOS, td) == NOTOK)
	return NOTOK;

    if (SExec (ts, &sis, psapd, setperms) == NOTOK) {
	advise (LLOG_EXCEPTIONS, NULLCP, "service not started at ssap: %s",
		SErrString (sa -> sa_reason));
	if (sa -> sa_cc > 0)
	    advise (LLOG_EXCEPTIONS, NULLCP, "   %*.*s",
		    sa -> sa_cc, sa -> sa_cc, sa -> sa_data);

	SAFREE (sa);
    }
		
    return DONE;
}

/* \f

 */

#define	RMASK \
    "\020\01HALFDUPLEX\02DUPLEX\03EXPEDITED\04MINORSYNC\05MAJORSYNC\06RESYNC\
\07ACTIVITY\010NEGOTIATED\011CAPABILITY\012EXCEPTIONS\013TYPEDATA"


static int  psapd (is, si)
register struct isoservent *is;
register struct SSAPindication *si;
{
    struct SSAPstart    sss;
    register struct SSAPstart  *ss = &sss;
    struct PSAPindication  pis;
    register struct PSAPabort *pa = &pis.pi_abort;
    struct RtSAPindication  rtis;
    register struct RtSAPabort *rta = &rtis.rti_abort;
    struct RoSAPindication  rois;
    register struct RoSAPpreject   *rop = &rois.roi_preject;

    if (strcmp (is -> is_provider, "ssap"))
	return OK;

    if (strcmp (is -> is_entity, "presentation")
	    && strcmp (is -> is_entity, "rts")
	    && strcmp (is -> is_entity, "ros"))
	return OK;

/* begin UGLY */
    (void) strcpy (buffer1, *(is -> is_tail - 2));
    (void) strcpy (buffer2, *(is -> is_tail - 1));
/* end UGLY */
    if (SInit (is -> is_tail - is -> is_vec, is -> is_vec, ss, si) == NOTOK)
	return NOTOK;
    advise (LLOG_NOTICE, NULLCP,
	    "S-CONNECT.INDICATION: <%d, %s, %s, %s, %s, %ld, %d>",
	    ss -> ss_sd, sprintref (&ss -> ss_connect),
	    saddr2str (&ss -> ss_calling), saddr2str (&ss -> ss_called),
	    sprintb (ss -> ss_requirements, RMASK), ss -> ss_isn,
	    ss -> ss_ssdusize);

    if (strcmp (is -> is_entity, "presentation") == 0) {
	if (PExec (ss, &pis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
		advise (LLOG_EXCEPTIONS, NULLCP,
			"service not started at psap: %s",
			PErrString (pa -> pa_reason));
		if (pa -> pa_cc > 0)
		    advise (LLOG_EXCEPTIONS, NULLCP, "   %*.*s",
			pa -> pa_cc, pa -> pa_cc, pa -> pa_data);
	}

	return DONE;
    }

    if (strcmp (is -> is_entity, "rts") == 0) {
	if (RtExec (ss, &rtis, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
	    advise (LLOG_EXCEPTIONS, NULLCP,
		    "service not started at rtsap: %s",
		    RtErrString (rta -> rta_reason));
	    if (rta -> rta_cc > 0)
		advise (LLOG_EXCEPTIONS, NULLCP, "   %*.*s",
			rta -> rta_cc, rta -> rta_cc, rta -> rta_data);
	}
    }
    else {
	if (RoExec (ss, &rois, buffer1, buffer2, NULLIFP, setperms) == NOTOK) {
	    advise (LLOG_EXCEPTIONS, NULLCP,
		    "service not started at rosap: %s",
		    RoErrString (rop -> rop_reason));
	    if (rop -> rop_cc > 0)
		advise (LLOG_EXCEPTIONS, NULLCP, "   %*.*s",
			rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
	}
    }

    return DONE;
}
#endif

/* \f

 */

static	arginit (vec)
char	**vec;
{
    int	    rflag;
    register char  *ap;
#ifdef	TCP
    int	    port;
    struct NSAPaddr *tcp_na;
    register struct servent *sp;
#endif
#ifdef	X25
    struct NSAPaddr *x25_na;
#endif
#ifdef	BRIDGE_X25
    struct NSAPaddr *bridge_na;
#endif
#ifdef	TP4
    register struct isoservent *is;
#endif
    struct stat st;

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

    isodetailor (myname, 0);
    ll_hdinit (pgm_log, myname);

    rflag = 0;

    (void) strcpy (myhost, TLocalHostName ());

    bzero ((char *) tas, sizeof tas);
    tz = tas;

#ifdef	TCP
    if (!(ts_stacks & TS_TCP))
	tcpservice = 0;
    if ((sp = getservbyname ("tsap", "tcp")) == NULL)
	advise (LLOG_EXCEPTIONS, NULLCP, "tcp/tsap: unknown service");

    tcp_na = tz -> ta_addrs;
    tcp_na -> na_type = NA_TCP;
    tcp_na -> na_subnet = ts_comm_tcp_default;
    tcp_na -> na_domain[0] = NULL;
    tcp_na -> na_port = sp ? sp -> s_port : htons ((u_short) 102);
    tz -> ta_naddr = 1;

    tz++;
#endif

#ifdef	X25
    if (!(ts_stacks & TS_X25))
	x25service = 0;

    x25_na = tz -> ta_addrs;
    x25_na -> na_type = NA_X25;
    x25_na -> na_subnet = ts_comm_x25_default;
    if (x25_local_dte && *x25_local_dte) {
	(void) strcpy (x25_na -> na_dte, x25_local_dte);
	x25_na -> na_dtelen = strlen (x25_na -> na_dte);
    }
    if (x25_local_pid && *x25_local_pid)
	x25_na -> na_pidlen =
	    str2sel (x25_local_pid, -1, x25_na -> na_pid, NPSIZE);
    tz -> ta_naddr = 1;

    tz++;
#endif

#ifdef	BRIDGE_X25
    if (!(ts_stacks & TS_BRG))
	bridgeservice = 0;

    bridge_na = tz -> ta_addrs;
    bridge_na -> na_type = NA_BRG;
    bridge_na -> na_subnet = ts_comm_x25_default;
    if (x25_bridge_listen && *x25_bridge_listen) {
	(void) strcpy (bridge_na -> na_dte, x25_bridge_listen);
	bridge_na -> na_dtelen = strlen (bridge_na -> na_dte);
    }
    if (x25_bridge_pid && *x25_bridge_pid)
	bridge_na -> na_pidlen =
	    str2sel (x25_bridge_pid, -1, bridge_na -> na_pid, NPSIZE);
    tz -> ta_naddr = 1;

    tz++;
#endif

#ifdef	TP4
    if (!(ts_stacks & TS_TP4))
	tp4service = 0;

    (void) setisoservent (0);
    while (is = getisoservent ())
	if (strcmp (is -> is_provider, "tsap") == 0
		&& (strcmp (*is -> is_vec, "tsapd-bootstrap") == 0
			|| access (*is -> is_vec, X_OK) != NOTOK)) {
	    if (strcmp (is -> is_entity, "isore") == 0)
		continue;

	    if (tz >= tas + NTADDRS) {
		advise (LLOG_EXCEPTIONS, NULLCP,
			"too many services, starting with %s",
			is -> is_entity);
		break;
	    }

	    bcopy (is -> is_selector, tz -> ta_selector,
		   tz -> ta_selectlen = is -> is_selectlen);
	    tz -> ta_naddr = 0;

	    tz++;
	}
    (void) endisoservent ();
#endif

    for (vec++; ap = *vec; vec++) {
	if (*ap == '-')
	    switch (*++ap) {
		case 'd':
		    debug++;
		    continue;
		
		case 't': 
		    ts_stacks = TS_TCP;
		    tcpservice = 1;
		    x25service = bridgeservice = tp4service = 0;
		    continue;

		case 'x': 
		    ts_stacks = TS_X25;
		    x25service = 1;
		    tcpservice = bridgeservice = tp4service = 0;
		    continue;

		case 'z': 
		    ts_stacks = TS_TP4;
		    tp4service = 1;
		    tcpservice = x25service = bridgeservice = 0;
		    continue;

		case 'b':
		    ts_stacks = TS_BRG;
		    bridgeservice = 1;
		    tcpservice = x25service = tp4service = 0;
		    continue;

		case 'r':
		    rflag = 1;
		    continue;

#ifdef	TCP
		case 'p': 
		    if ((ap = *++vec) == NULL
			    || *ap == '-'
			    || (port = atoi (ap)) <= 0)
			adios (NULLCP, "usage: %s -p portno", myname);
		    tcp_na -> na_port = htons ((u_short) port);
		    continue;
#endif

#ifdef X25
		/* This permits listening on a specific subaddress. */
		case 'a':
		    if ((ap = *++vec) == NULL || *ap == '-')
			adios (NULLCP, "usage: %s -a x121address", myname);
		    (void) strcpy (x25_na -> na_dte, ap);
		    x25_na -> na_dtelen = strlen (ap);
		    continue;

		/* This permits listening on a specific protocol id.
		   In fact, SunLink X.25 lets you listen on a protocol
		   id mask, but let's keep it simple. */
		case 'i':
		    if ((ap = *++vec) == NULL || *ap == '-' )
			adios (NULLCP, "usage: %s -i pid", myname);
		    x25_na -> na_pidlen =
			str2sel (ap, -1, x25_na -> na_pid, NPSIZE);
		    continue;
#endif

#ifdef BRIDGE_X25
		case 'A':
		    if ((ap = *++vec) == NULL ||
			*ap == '-')
			adios (NULLCP, "usage: %s -A x121address", myname);
		    (void) strcpy (bridge_na -> na_dte, ap);
		    bridge_na -> na_dtelen = strlen (ap);
		    continue;

		case 'I':
		    if ((ap = *++vec) == NULL || *ap == '-')
			adios (NULLCP, "usage: %s -I pid", myname);
		    bridge_na -> na_pidlen =
			str2sel (ap, -1, bridge_na -> na_pid, NPSIZE);
		    continue;
#endif

		default: 
		    adios (NULLCP, "-%s: unknown switch", ap);
	    }

	adios (NULLCP, "usage: %s [switches]", myname);
    }

    if (!rflag
	    && getuid () == 0
	    && stat (ap = isodefile ("isoservices", 0), &st) != NOTOK
	    && st.st_uid != 0)
	adios (NULLCP, "%s not owned by root", ap);
}

/* \f

 */

static  envinit () {
    int     i,
            sd;

    nbits = getdtablesize ();

    if (debug == 0 && !(debug = isatty (2))) {
	for (i = 0; i < 5; i++) {
	    switch (fork ()) {
		case NOTOK: 
		    sleep (5);
		    continue;

		case OK: 
		    break;

		default: 
		    _exit (0);
	    }
	    break;
	}

	(void) chdir ("/");

	if ((sd = open ("/dev/null", O_RDWR)) == NOTOK)
	    adios ("/dev/null", "unable to read");
	if (sd != 0)
	    (void) dup2 (sd, 0), (void) close (sd);
	(void) dup2 (0, 1);
	(void) dup2 (0, 2);

#ifdef	TIOCNOTTY
	if ((sd = open ("/dev/tty", O_RDWR)) != NOTOK) {
	    (void) ioctl (sd, TIOCNOTTY, NULLCP);
	    (void) close (sd);
	}
#else
#ifdef	SYS5
	(void) setpgrp ();
	(void) signal (SIGINT, SIG_IGN);
	(void) signal (SIGQUIT, SIG_IGN);
#endif
#endif
    }
    else
	ll_dbinit (pgm_log, myname);

#ifndef	sun		/* damn YP... */
    for (sd = 3; sd < nbits; sd++)
	if (pgm_log -> ll_fd != sd)
	    (void) close (sd);
#endif

    (void) signal (SIGPIPE, SIG_IGN);

    ll_hdinit (pgm_log, myname);
    advise (LLOG_NOTICE, NULLCP, "starting");
}

/* \f

   ERRORS */

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

    va_start (ap);
    
    _ll_log (pgm_log, LLOG_FATAL, ap);

    va_end (ap);

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

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


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

    va_start (ap);
    
    code = va_arg (ap, int);

    _ll_log (pgm_log, code, ap);

    va_end (ap);
}
#else
/* VARARGS */

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