TIP: Click on subject to list as thread! ANSI
echo: locsysop
to: All
from: Paul Edwards
date: 1997-04-26 23:31:10
subject: newsgroups

Well, I've got my first newsgroup come in!  I can only get one newsgroup at
a time, but that's just a minor wart which I know about and expect a
solution to soon.  So I have moved onto the UUCP side.

I have made uucico.c available for FREQ, which is the negotiation that the
program I run will be using.  All I know is the first step, which is that
it sends out Shere=scorpio (my machine is called scorpio).

I'm still working on getting this program to run automatically, and getting
some data to send.  Here's a snippet of code from uucico if that's of any
interest...

  if (! fchat (qconn, puuconf, &qsys->uuconf_schat, qsys,
	       (const struct uuconf_dialer *) NULL,
	       (const char *) NULL, FALSE, zport,
	       iconn_baud (qconn)))
    return FALSE;

  *pfcalled = TRUE;
  istart_time = ixsysdep_time ((long *) NULL);

  *pterr = STATUS_HANDSHAKE_FAILED;

  /* We should now see "Shere" from the other system.  Newer systems
     send "Shere=foo" where foo is the remote name.  */
  zstr = zget_uucp_cmd (qconn, TRUE, fstrip);
  if (zstr == NULL)
    return FALSE;

  if (strncmp (zstr, "Shere", 5) != 0)
    {
      ulog (LOG_ERROR, "Bad startup string (expected
\"Shere\" got \"%s\")",
	    zstr);
      ubuffree (zstr);
      return FALSE;
    }

  ulog (LOG_NORMAL, "Login successful");

  qstat->ttype = STATUS_TALKING;
  qstat->ilast = ixsysdep_time ((long *) NULL);
  qstat->cretries = 0;
  qstat->cwait = 0;
  if (! fsysdep_set_status (qsys, qstat))
    return FALSE;

  if (zstr[5] == '=')
    {
      const char *zheresys;
      size_t clen;
      int icmp;

      /* Some UUCP packages only provide seven characters in the Shere
	 machine name.  Others only provide fourteen.  */
      zheresys = zstr + 6;
      clen = strlen (zheresys);
      if (clen == 7 || clen == 14)
	icmp = strncmp (zheresys, qsys->uuconf_zname, clen);
      else
	icmp = strcmp (zheresys, qsys->uuconf_zname);
      if (icmp != 0)
	{
	  if (qsys->uuconf_pzalias != NULL)
	    {
	      char **pz;

	      for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++)
		{
		  if (clen == 7 || clen == 14)
		    icmp = strncmp (zheresys, *pz, clen);
		  else
		    icmp = strcmp (zheresys, *pz);
		  if (icmp == 0)
		    break;
		}
	    }
	  if (icmp != 0)
	    {
	      ulog (LOG_ERROR, "Called wrong system (%s)", zheresys);
	      ubuffree (zstr);
	      return FALSE;
	    }
	}
    }
#if DEBUG > 1
  else if (zstr[5] != '\0')
    DEBUG_MESSAGE1 (DEBUG_HANDSHAKE,
		    "fdo_call: Strange Shere: %s", zstr);
#endif

  ubuffree (zstr);

  /* We now send "S" name switches, where name is our UUCP name.  If
     we are using sequence numbers with this system, we send a -Q
     argument with the sequence number.  If the call-timegrade command
     was used, we send a -p argument and a -vgrade= argument with the
     grade to send us (we send both argument to make it more likely
     that one is recognized).  We always send a -N (for new) switch
     indicating what new features we support.  */
  {
    long ival;
    char bgrade;
    char *zsend;
    boolean fret;

    /* Determine the grade we should request of the other system.  A
       '\0' means that no restrictions have been made.  */
    if (! ftimespan_match (qsys->uuconf_qcalltimegrade, &ival,
			   (int *) NULL))
      bgrade = '\0';
    else
      bgrade = (char) ival;

    /* Determine the name we will call ourselves.  */
    if (qsys->uuconf_zlocalname != NULL)
      qdaemon->zlocalname = qsys->uuconf_zlocalname;
    else
      {
	iuuconf = uuconf_localname (puuconf, &qdaemon->zlocalname);
	if (iuuconf == UUCONF_NOT_FOUND)
	  {
	    qdaemon->zlocalname = zsysdep_localname ();
	    if (qdaemon->zlocalname == NULL)
	      return FALSE;
	  }
	else if (iuuconf != UUCONF_SUCCESS)
	  {
	    ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
	    return FALSE;
	  }
      }	    

    zsend = zbufalc (strlen (qdaemon->zlocalname) + 70);
    if (! qsys->uuconf_fsequence)
      {
	if (bgrade == '\0')
	  sprintf (zsend, "S%s -R -N0%o", qdaemon->zlocalname,
		   (unsigned int) (FEATURE_SIZES
				   | FEATURE_EXEC
				   | FEATURE_RESTART));
	else
	  sprintf (zsend, "S%s -p%c -vgrade=%c -R -N0%o",
		   qdaemon->zlocalname, bgrade, bgrade,
		   (unsigned int) (FEATURE_SIZES
				   | FEATURE_EXEC
				   | FEATURE_RESTART));
      }
    else
      {
	long iseq;

	iseq = ixsysdep_get_sequence (qsys);
	if (iseq < 0)
	  return FALSE;
	if (bgrade == '\0')
	  sprintf (zsend, "S%s -Q%ld -R -N0%o", qdaemon->zlocalname, iseq,
		   (unsigned int) (FEATURE_SIZES
				   | FEATURE_EXEC
				   | FEATURE_RESTART));
	else
	  sprintf (zsend, "S%s -Q%ld -p%c -vgrade=%c -R -N0%o",
		   qdaemon->zlocalname, iseq, bgrade, bgrade,
		   (unsigned int) (FEATURE_SIZES
				   | FEATURE_EXEC
				   | FEATURE_RESTART));
      }

    fret = fsend_uucp_cmd (qconn, zsend);
    ubuffree (zsend);
    if (! fret)
	return FALSE;
  }

  /* Now we should see ROK or Rreason where reason gives a cryptic
     reason for failure.  If we are talking to a counterpart, we will
     get back ROKN, possibly with a feature bitfield attached.  */
  zstr = zget_uucp_cmd (qconn, TRUE, fstrip);
  if (zstr == NULL)
    return FALSE;

  if (zstr[0] != 'R')
    {
      ulog (LOG_ERROR, "Bad response to handshake string (%s)",
	    zstr);
      ubuffree (zstr);
      return FALSE;
    }

  if (strncmp (zstr + 1, "OKN", sizeof "OKN" - 1) == 0)
    {
      if (zstr[sizeof "ROKN" - 1] == '\0')
	qdaemon->ifeatures |= FEATURE_SIZES | FEATURE_V103;
      else
	qdaemon->ifeatures |= (int) strtol (zstr + sizeof "ROKN" - 1,
					   (char **) NULL, 0);
    }
  else if (strncmp (zstr + 1, "OK", sizeof "OK" - 1) == 0)
    {
      if (zstr[sizeof "ROK" - 1] != '\0')
	{
	  char *zopt;

	  /* SVR4 UUCP returns options following the ROK string.  */
	  zopt = zstr + sizeof "ROK" - 1;
	  while (*zopt != '\0')
	    {
	      char b;
	      long c;
	      char *zend;

	      b = *zopt++;
	      if (isspace (b) || b != '-')
		continue;
	      switch (*zopt)
		{
		case 'R':
		  qdaemon->ifeatures |= (FEATURE_RESTART
					 | FEATURE_SVR4
					 | FEATURE_SIZES);
		  break;
		case 'U':
		  c = strtol (zopt, &zend, 0);
		  if (c > 0 && c <= LONG_MAX / (long) 512)
		    qdaemon->cmax_receive = c * (long) 512;
		  zopt = zend;
		  break;
		}
	      while (*zopt != '\0' && ! isspace (*zopt))
		++zopt;
	    }
	}
    }
  else if (strcmp (zstr + 1, "CB") == 0)
    {
      ulog (LOG_NORMAL, "Remote system will call back");
      qstat->ttype = STATUS_COMPLETE;
      (void) fsysdep_set_status (qsys, qstat);
      ubuffree (zstr);
      return TRUE;
    }
  else
    {
      ulog (LOG_ERROR, "Handshake failed (%s)", zstr + 1);
      ubuffree (zstr);
      return FALSE;
    }

  ubuffree (zstr);

  /* The slave should now send \020Pprotos\0 where protos is a list of
     supported protocols.  Each protocol is a single character.  */
  zstr = zget_uucp_cmd (qconn, TRUE, fstrip);
  if (zstr == NULL)
    return FALSE;

  if (zstr[0] != 'P')
    {
      ulog (LOG_ERROR, "Bad protocol handshake (%s)", zstr);
      ubuffree (zstr);
      return FALSE;
    }

  /* Determine the reliability characteristics of the connection by
     combining information for the port and the dialer.  If we have no
     information, default to a reliable eight-bit full-duplex
     connection.  */
  if (qconn->qport != NULL
      && (qconn->qport->uuconf_ireliable &
UUCONF_RELIABLE_SPECIFIED) != 0)
    qdaemon->ireliable = qconn->qport->uuconf_ireliable;
  if (qdialer != NULL
      && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
    {
      if (qdaemon->ireliable != 0)
	qdaemon->ireliable &= qdialer->uuconf_ireliable;
      else
	qdaemon->ireliable = qdialer->uuconf_ireliable;
    }
  if (qdaemon->ireliable == 0)
    qdaemon->ireliable = (UUCONF_RELIABLE_RELIABLE
			  | UUCONF_RELIABLE_EIGHT
			  | UUCONF_RELIABLE_FULLDUPLEX
			  | UUCONF_RELIABLE_SPECIFIED);

  /* Now decide which protocol to use.  The system and the port may
     have their own list of protocols.  */
  {
    int i;
    char ab[5];

    i = CPROTOCOLS;
    if (qsys->uuconf_zprotocols != NULL
	|| (qconn->qport != NULL
	    && qconn->qport->uuconf_zprotocols != NULL))
      {
	const char *zproto;

	if (qsys->uuconf_zprotocols != NULL)
	  zproto = qsys->uuconf_zprotocols;
	else
	  zproto = qconn->qport->uuconf_zprotocols;
	for (; *zproto != '\0'; zproto++)
	  {
	    if (strchr (zstr + 1, *zproto) != NULL)
	      {
		for (i = 0; i < CPROTOCOLS; i++)
		  if (asProtocols[i].bname == *zproto)
		    break;
		if (i < CPROTOCOLS)
		  break;
	      }
	  }
      }
    else
      {
	/* If neither the system nor the port specified a list of
	   protocols, we want only protocols that match the known
	   reliability of the dialer and the port.  */
	for (i = 0; i < CPROTOCOLS; i++)
	  {
	    int ipr;

	    ipr = asProtocols[i].ireliable;
	    if ((ipr & qdaemon->ireliable) != ipr)
	      continue;
	    if (strchr (zstr + 1, asProtocols[i].bname) != NULL)
	      break;
	  }
      }

    ubuffree (zstr);

    if (i >= CPROTOCOLS)
      {
	(void) fsend_uucp_cmd (qconn, "UN");
	ulog (LOG_ERROR, "No mutually supported protocols");
	return FALSE;
      }

    qdaemon->qproto = &asProtocols[i];

    /* If we are using a half-duplex line, act as though we have only
       a single channel; otherwise we might start a send and a receive
       at the same time.  */
    if ((qdaemon->ireliable & UUCONF_RELIABLE_FULLDUPLEX) == 0)
      qdaemon->cchans = 1;
    else
      qdaemon->cchans = asProtocols[i].cchans;

    sprintf (ab, "U%c", qdaemon->qproto->bname);
    if (! fsend_uucp_cmd (qconn, ab))
      return FALSE;
  }

  /* Run any protocol parameter commands.  */
  if (qdaemon->qproto->qcmds != NULL)
    {
      if (qsys->uuconf_qproto_params != NULL)
	uapply_proto_params (puuconf, qdaemon->qproto->bname,
			     qdaemon->qproto->qcmds,
			     qsys->uuconf_qproto_params);
      if (qconn->qport != NULL
	  && qconn->qport->uuconf_qproto_params != NULL)
	uapply_proto_params (puuconf, qdaemon->qproto->bname,
			     qdaemon->qproto->qcmds,
			     qconn->qport->uuconf_qproto_params);
      if (qdialer != NULL
	  && qdialer->uuconf_qproto_params != NULL)
	uapply_proto_params (puuconf, qdaemon->qproto->bname,
			     qdaemon->qproto->qcmds,
			     qdialer->uuconf_qproto_params);
    }

  /* Turn on the selected protocol.  */
  if (! (*qdaemon->qproto->pfstart) (qdaemon, &zlog))
    return FALSE;
  if (zlog == NULL)
    {
      zlog = zbufalc (sizeof "protocol ''" + 1);
      sprintf (zlog, "protocol '%c'", qdaemon->qproto->bname);
    }
  ulog (LOG_NORMAL, "Handshake successful (%s)", zlog);
  ubuffree (zlog);

  *pterr = STATUS_FAILED;

  {
    boolean fret;
    long iend_time;

    fret = floop (qdaemon);

    /* Now send the hangup message.  As the caller, we send six O's
       and expect to receive seven O's.  We send the six O's twice to
       help the other side.  We don't worry about errors here.  */
    if (fsend_uucp_cmd (qconn, "OOOOOO")
	&& fsend_uucp_cmd (qconn, "OOOOOO"))
      {
	int i, fdone;

	/* We look for the remote hangup string to ensure that the
	   modem has sent out our hangup string.  This is only
	   necessary because some versions of UUCP complain if they
	   don't get the hangup string.  The remote site should send 7
	   O's, but some versions of UUCP only send 6.  We look for
	   the string several times because supposedly some
	   implementations send some garbage after the last packet but
	   before the hangup string.  */
	for (i = 0; i < 25; i++)
	  {
	    zstr = zget_uucp_cmd (qconn, FALSE, fstrip);
	    if (zstr == NULL)
	      break;
	    fdone = strstr (zstr, "OOOOOO") != NULL;
	    ubuffree (zstr);
	    if (fdone)
	      break;
	  }
      }

    iend_time = ixsysdep_time ((long *) NULL);

    ulog (LOG_NORMAL, "Call complete (%ld seconds %ld bytes %ld bps)",
	  iend_time - istart_time,
	  qdaemon->csent + qdaemon->creceived,
	  (iend_time != istart_time
	   ? (qdaemon->csent + qdaemon->creceived) / (iend_time - istart_time)
	   : 0));

    if (fret)
      {
	qstat->ttype = STATUS_COMPLETE;
	qstat->ilast = iend_time;
	(void) fsysdep_set_status (qsys, qstat);
      }

    if (qdaemon->irunuuxqt == UUCONF_RUNUUXQT_PERCALL
	|| (qdaemon->irunuuxqt > 0 && qdaemon->cxfiles_received > 0))
      (void) fspawn_uuxqt (TRUE, qdaemon->qsys->uuconf_zname,
			   qdaemon->zconfig);

    return fret;
  }
}
@EOT:

---
* Origin: X (3:711/934.9)

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.