view 3rdparty/packages/uucpbb/src/openuucp.c @ 3295:6b7a7b233925 default tip

makefile: Allow PORTS with level1/2 mix https://sourceforge.net/p/nitros9/feature-requests/10/
author Tormod Volden <debian.tormod@gmail.com>
date Tue, 19 Apr 2022 18:12:17 +0200
parents 5ba8e711a1a3
children
line wrap: on
line source

/*  openuucp.c    Establish a uucp connection with the remote.
    Copyright (C) 1990, 1993  Rick Adams and Bob Billson

    This file is part of the OS-9 UUCP package, UUCPbb.

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

    The author of UUCPbb, Bob Billson, can be contacted at:
    bob@kc2wz.bubble.org  or  uunet!kc2wz!bob  or  by snail mail:
    21 Bates Way, Westfield, NJ 07090
*/

#include "uucp.h" 
#include "uucico.h"
#include <ctype.h>

#define DLE  '\x10'                                /* DLE character */

static char *handshake_ok = "Handshake successful",
            *no_proto = "no supported protocol",
            *startG = "start g protocol handshake",
            *whoweare = "telling remote who we are: ";


/**********************************\
* open uucp session in master mode *
\**********************************/

int mopenuucp()
{
     char string[200];
     register char *p;
     int i;

     p = string;

     if (debuglvl > 0)
          fprintf (log, "mopenuucp: %s\n", startG);

     /* receive "Shere" from remote */
     if (recv0 (p) == TIMEDOUT)
       {
          logerror ("mopenuucp: remote didn't send Shere");
          return (ABORT);
       }

     if (strncmp (p, "Shere", 5) != 0)
       {
          logerror ("mopenuucp: Bad Shere string from remote");

          if (debuglvl > 3)
               fprintf (log, "mopenuucp: remote sent: %s\n", p);

          return (ABORT);
       }

     if (debuglvl > 0)
          fputs ("mopenuucp: got Shere\n", log);

     lognorm ("Login successful");

     /* called the right remote, right? */
     if (*(p+5) == '=')
       {
          if (strncmp (p+6, sysname, strlen (sysname)) != 0)     /* oops!! */
            {
               char tmp[60];

               sprintf (tmp, "called wrong system (%s)", p+6);
               logerror (tmp);
               return (ABORT);
            }
       }
     else if (*(p+5) != '\0')
       {
          char tmp[65];

          sprintf (tmp, "mopenuucp: Strange Shere: %s", p);
          logerror (tmp);
       }

     /* tell 'em who we are */
     sprintf (p, "S%s", nodename);

     if (debuglvl > 0)
          fprintf (log, "mopenuucp: %s%s\n", whoweare, p);

     send0 (p);

     /* find out what remote thinks of us */
     if (recv0 (p) == TIMEDOUT)
          return (ABORT);

     if (*p != 'R')
       {
          char tmp[128];

          sprintf (tmp, "Bad response to handshake string (%s)", p);
          logerror (tmp);
          return (ABORT);
       }

      if (strncmp (p+1, "OK", 2) == 0)
        {
           if (debuglvl > 0)
                fputs ("mopenuucp: remote says we are OK\n", log);
        }
      else if (strcmp (p+1, "LCK") == 0)
       {
          logerror ("Remote says we are already talking");
          return (ABORT);
       }
     else if (strcmp (p+1, "CB") == 0)
       {
          logerror ("Remote will call back");
          return (ABORT);
       }
     else if (strcmp (p+1, "BADSEQ") == 0)
       {
          logerror ("bad sequence number");
          return (ABORT);
       }
     else
       {
          char tmp[65];

          sprintf (tmp, "Handshake failed (%s)", p+1);
          logerror (tmp);
       }

     /* receive list of supported protocols from remote */
     if (recv0 (p) == TIMEDOUT)
          return (ABORT);

     /* is "g" protocol supported? */
     if (*p != 'P')
       {
          logerror ("mopenuucp: Bad protocol handshake");
          return (ABORT);
       }

     if (strstr (p, "g") == NULL)
       {
          send0 ("UN");
          logerror (no_proto);
          return (ABORT);
       }

     /* tell 'em to use g protocol */
     protocol = 'g';
     sprintf (p, "U%c", protocol);
     send0 (p);
     sprintf (p, "%s (protocol '%c')", handshake_ok, protocol);
     lognorm (p);
     return (MS_SNDRCV);
}



/*********************************\
* open uucp session in slave mode *
\*********************************/

int sopenuucp()
{
     char string[200];
     register char *p;
     char *incoming = "Incoming call from ";

     p = string;

     if (debuglvl > 0)
          fprintf (log, "sopenuucp: %s\n", startG);

     /* send "Shere" to remote */
     sprintf (p, "Shere=%s", nodename);

     if (debuglvl > 0)
          fprintf (log, "sopenuucp: %s%s\n", whoweare, p);

     send0 (p);

     /* find out who they are */
     if (recv0 (p) == TIMEDOUT)
          return (ABORT);

     if (*p != 'S')
       {
          strcpy (sysname, "unknown");
          sprintf (p, "%s%s (port %s)", incoming, sysname, device);
          lognorm (p);
          logerror ("sopenuucp: Bad introduction string");
          return (ABORT);
       }

     if (debuglvl > 0)
          fputs ("sopenuucp: got remote's S<hostname>\n", log);

     /* isolate system name */
     if ((p = strchr (string, ' ')) != NULL)
          *p = '\0';

     p = string;
     strcpy (sysname, p+1);

     /* log the connection */
     sprintf (p, "%s%s on port %s",
                 incoming, sysname, *device != '\0' ? device : "unknown");
     lognorm (p);

     /* Are they allowed in here? */
     if (SystemIsOK (FALSE) == FALSE)
       {
          send0 ("RYou are unknown to me");
          sprintf (p, "WARNING--call from unknown system: %s", sysname);
          lognorm (p);
          return (ABORT);
       }

     /* For now we don't tell the remote we will call them back or reject
        the login otherwise.  Instead, we tell remote that all is fine. */
     send0 ("ROK");

     /* send list of supported protocols to remote */
     send0 ("Pg");

     /* is "g" protocol okay? */
     if (recv0 (p) == TIMEDOUT)
          return (ABORT);

     /* Ug if okay, UN if not */
     if (*p != 'U'  ||  *(p+2) != '\0')
       {
          logerror ("sopenuucp: Bad protocol response string");
          return (ABORT);
       }

     if (*(p+1) == 'N')
       {
          logerror ("sopenuucp: No supported protocol");
          return (ABORT);
       }
     protocol = *(p+1);
     sprintf (string, "%s (protocol '%c')", handshake_ok, protocol);
     lognorm (string);
     return (MS_SNDRCV);
}



/* Is this valid system?  The remote's name is in the global variable
   'sysname'.  TRUE is returned if we talk to the remote.  FALSE if not or on
    error. */

int SystemIsOK (quitonerror)
int quitonerror;
{
     char buff[SYSLINE];
     int sysnamlen = strlen (sysname);
     register char *p;
     char *p1;
     FILE *fpsys;

     p = buff;

     if ((fpsys = fopen (SYSTEMS, "r")) == NULL)
       {
          openlog();
          strcpy (p, "SystemIsOk: can't open Systems file");
          logerror (p);
          closelog();

          if (quitonerror)
               fatal (p);
          else
               return (FALSE);
       }

     /* ignore comment lines beginning with #, <space>, <tab> or CR */
     while (mfgets (p, SYSLINE, fpsys) != NULL)
          if (ISCOMMENT (*p) == FALSE)
            {
               /* isolate system name */
               if ((p1 = strchr (p, ' ')) != NULL)
                    *p1 = '\0';

               if (strucmp (sysname, p) == 0)
                 {
                    fclose (fpsys);
                    return (TRUE);
                 }
            }

     /* no entry for this system */
     fclose (fpsys);
     sprintf (p, "no entry in Systems file for: %s", sysname);
     openlog();
     logerror (p);

     if (!quiet  &&  log != stderr)
          fprintf (stderr, "%s\n\n", buff);

     return (FALSE);
}



/* Receive a NULL terminated string.  This is one used when no protocol is
   being used.  The basic idea for this is borrowed from Taylor (GNU) UUCP. */

int recv0 (string)
char *string;
{
     register char *p;
     char c;
     flag gotDLE = FALSE;

     if (debuglvl > 7)
          fputs ("<< ", log);

     /* Keep reading the port until we time out or get an ending null */
     p = string;
     while (readport (&c, PKTTIME, MAXTRY) != TIMEDOUT)
       {
          /* strip any parity bit */
          c &= 0x7f;

          /* Log the byte if the debug level is high enough.  Don't bother
             logging the terminating null since we know it must be there. */

          if (debuglvl > 7)
               if (gotDLE  &&  c == '\0')
                    ;
               else
                    chardump (c);

          /* Look for the DLE to indicate the start of a null-terminated
             message.   We ignored everything until we get the DLE. */
          if (!gotDLE)
            {
               if (c == DLE)
                    gotDLE = TRUE;

               continue;
            }

          /* We got the DLE, so start assembling the string until we get a
             NULL signaling the end. */

          /* Huh?  Another DLE?  Something happened here.  Act like it is the
             first one we saw. */
          if (c == DLE)
            {
               p = string;
               continue;
            }

          /* Some systems send trailing \n on Shere line.  This is a definite
             no-no and should not occur...but...  This mod should be safe. */            if (c == '\x0d'  ||  c == '\x0a')
               c = '\0';

          *p++ = c;

          if (c == '\0')
            {
               if (debuglvl > 7)
                    putc ('\n', log);

               return (TRUE);
            }
       }
     /* we must have timed out */
     return (TIMEDOUT);
}



/* Send a NULL terminated string.  This is only used when no protocol is
   being used. */

int send0 (string)
register char *string;
{
     int lport, result, sendlen = strlen (string) + 1;

     lport = port == 0  ? 1 : port;

     if (debuglvl > 7)
       {
          fputs (">> [$10]", log);
          strdump (string);
       }

     /* send DLE... */
     if ((result = write (lport, "\x10", 1)) != 1)
          if (debuglvl > 0)
               logerror ("send0: didn't write enough data, probably won't write the rest either.");

     /* ...and the rest of the string including its ending \0 */
     result = write (lport, string, sendlen);
     return (result == sendlen ? TRUE : FALSE);
}



/* dump out string for diagnostic output */

int strdump (string)
char *string;
{
     register char *c;

     for (c = string;  *c != '\0';  ++c)
          chardump (*c);

     putc ('\n', log);
}



/* Dump out a char for diagnostic output.  This is called by strdump() above
   and recv0(). */

int chardump (c)
register char c;
{
     if (isprint (c))
       {
          if (c == '\x0d')
               fputs ("<CR>", log);
          else if (c == '\x0a')
               fputs ("<LF>", log);
          else
               fprintf (log, "%c", c);
       }
     else
          fprintf (log, "[$%02x]", c & 0xff);
}