Annotation of coherent/e/bin/ckermit/ckcnet.c, revision 1.1.1.1

1.1       root        1: char *cknetv = "Network support, 5A(015) 23 Nov 92";
                      2: 
                      3: /*  C K C N E T  --  Network support  */
                      4: /*
                      5:   Authors:
                      6: 
                      7:   Frank da Cruz ([email protected], [email protected]),
                      8:     Columbia University Center for Computing Activities.
                      9:   netopen() routine for TCP/IP originally by Ken Yap, Rochester University
                     10:     ([email protected]) (no longer at that address).
                     11:   Missing pieces for Excelan sockets library from William Bader, Moravian
                     12:     College <[email protected]>.
                     13:   TELNET protocol by Frank da Cruz.
                     14:   TGV MultiNet code by Frank da Cruz.
                     15:   MultiNet code adapted to WIN/TCP by Ray Hunter of TWG.
                     16:   MultiNet code adapted to DEC TCP/IP by Lee Tibbert of DEC and Frank da Cruz.
                     17:   SunLink X.25 support by Marcello Frutig, Catholic University,
                     18:     Rio de Janeiro, Brazil ([email protected]) with fixes from
                     19:     Stefaan Eeckels, Eurokom, Luxembourg.
                     20:   Other contributions as indicated below.
                     21: 
                     22:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
                     23:   York.  Permission is granted to any individual or institution to use this
                     24:   software as long as it is not sold for profit.  This copyright notice must be
                     25:   retained.  This software may not be included in commercial products without
                     26:   written permission of Columbia University.
                     27: */
                     28: 
                     29: #include "ckcdeb.h"
                     30: #include "ckcker.h"
                     31: #ifdef I386IX                          /* Has to come before ckcnet.h in */
                     32: #include <errno.h>                     /* this version, but after in others */
                     33: #endif /* I386IX */
                     34: #include "ckcnet.h"
                     35: 
                     36: #ifdef NETCONN
                     37: /* Don't need these if there is no network support. */
                     38: 
                     39: #ifdef WINTCP
                     40: 
                     41: #include <errno.h>
                     42: #include <setjmp.h>
                     43: #include <signal.h>
                     44: /*
                     45:  * The WIN/TCP code path is the same as that for Multinet.  Only the routine
                     46:  * names have changed ...
                     47:  */
                     48: #define socket_errno   errno
                     49: #define socket_read    netread
                     50: #define socket_ioctl   ioctl
                     51: #define socket_write   netwrite
                     52: #define socket_perror   win$perror
                     53: #define socket_close   netclose
                     54: 
                     55: #else /* Not WINTCP */
                     56: #ifndef I386IX
                     57: #include <errno.h>
                     58: #endif /* I386IX */
                     59: #include <signal.h>
                     60: #ifndef ZILOG
                     61: #include <setjmp.h>
                     62: #else
                     63: #include <setret.h>
                     64: #endif /* ZILOG */
                     65: #endif /* WINTCP */
                     66: 
                     67: #ifdef datageneral                     /* Data General AOS/VS */
                     68: #include <:usr:include:vs_tcp_errno.h>
                     69: #include <:usr:include:sys:vs_tcp_types.h>
                     70: #include <:usr:include:sys:socket.h>
                     71: #include <:usr:include:netinet:in.h>
                     72: #include <:usr:include:netdb.h>
                     73: #endif /* datageneral */
                     74: 
                     75: extern SIGTYP (*saval)();              /* For saving alarm handler */
                     76: 
                     77: _PROTOTYP( VOID bgchk, (void) );
                     78: 
                     79: extern int                             /* External variables */
                     80:   duplex, debses, seslog, ttyfd, quiet, msgflg;
                     81: 
                     82: #ifdef SVR4
                     83: /*
                     84:   These suggested by Rob Healey, [email protected], to avoid
                     85:   bugs in Berkeley compatibility library on Sys V R4 systems, but untested
                     86:   by me (fdc).  Remove this bit if it gives you trouble.
                     87:   (Later corrected by Marc Boucher <[email protected]> because
                     88:   bzero/bcopy are not argument-compatible with memset/memcpy|memmove.)
                     89: */
                     90: #define bzero(s,n) memset(s,0,n)
                     91: #define bcopy(h,a,l) memmove(a,h,l)
                     92: #else
                     93: #ifdef PTX                             /* Sequent DYNIX PTX 1.3 */
                     94: #define bzero(s,n) memset(s,0,n)
                     95: #define bcopy(h,a,l) memcpy(a,h,l)
                     96: #endif /* PTX */
                     97: #endif /* SVR4 */
                     98: 
                     99: #define NAMECPYL 100                   /* Local copy of hostname */
                    100: static char namecopy[NAMECPYL];
                    101: 
                    102: char ipaddr[20] = { '\0' };            /* Global copy of IP address */
                    103: 
                    104: /*
                    105:   VMSTCPIP means "DEC_TCPIP or MULTINET or WINTCP" (defined in ckcnet.h).
                    106: */
                    107: #ifdef VMSTCPIP
                    108: /*
                    109:   General global variables, but so far used only by MultiNet and WIN/TCP.
                    110:   Kept within #ifdef MULTINET..#endif to keep strict compilers (and lint)
                    111:   from complaining about unused variables.
                    112: */
                    113: static jmp_buf njbuf;                  /* For timeout longjumps */
                    114: #endif /* VMSTCPIP */
                    115: 
                    116: #endif /* NETCONN */
                    117: 
                    118: int ttnet = NET_NONE;                  /* Network type */
                    119: int ttnproto = NP_NONE;                        /* Network virtual terminal protocol */
                    120: int tn_init = 0;                       /* Telnet protocol initialized flag */
                    121: int tn_duplex = 1;                     /* Initial echo status */
                    122: char *tn_term = NULL;                  /* Terminal type override */
                    123: int tn_nlm = 1;                                /* Telnet CR -> CR LF mode */
                    124: 
                    125: #ifndef NETCONN
                    126: /*
                    127:   Network support not defined.
                    128:   Dummy functions here in case #ifdef's forgotten elsewhere.
                    129: */
                    130: int                                    /* Open network connection */
                    131: netopen(name, lcl, nett) char *name; int *lcl, nett; {
                    132:     return(-1);
                    133: }
                    134: int                                    /* Close network connection */
                    135: netclos() {
                    136:     return(-1);
                    137: }
                    138: int                                    /* Check network input buffer */
                    139: nettchk() {
                    140:     return(-1);
                    141: }
                    142: int                                    /* Flush network input buffer */
                    143: netflui() {
                    144:     return(-1);
                    145: }
                    146: int                                    /* Send network BREAK */
                    147: netbreak() {
                    148:     return(-1);
                    149: }
                    150: int                                    /* Input character from network */
                    151: netinc(timo) int timo; {
                    152: }
                    153: int                                    /* Output character to network */
                    154: #ifdef CK_ANSIC
                    155: nettoc(char c)
                    156: #else
                    157: nettoc(c) char c;
                    158: #endif /* CK_ANSIC */
                    159: /* nettoc */ {
                    160:     return(-1);
                    161: }
                    162: int
                    163: nettol(s,n) char *s; int n; {
                    164:     return(-1);
                    165: }
                    166: 
                    167: #else /* NETCONN is defined (rest of this module...) */
                    168: 
                    169: #ifdef VMSTCPIP
                    170: 
                    171: /* For buffered network reads... */
                    172: /*
                    173:   If the buffering code is written right, it shouldn't matter how long this
                    174:   buffer is -- it could even be shorter than a Kermit packet.
                    175: */
                    176: #define TTIBUFL 8192                   /* Maybe 8K?... */
                    177: 
                    178: CHAR   ttibuf[TTIBUFL+1];
                    179: int    ttibp = 0, ttibn = 0;
                    180: /*
                    181:   Read bytes from network into internal buffer ttibuf[].
                    182:   To be called when input buffer is empty, i.e. when ttibn == 0.
                    183: 
                    184:   Other network reading routines, like ttinc, ttinl, ttxin, should check the
                    185:   internal buffer first, and call this routine for a refill if necessary.
                    186: 
                    187:   Returns -1 on error, 0 if nothing happens.  When data is read successfully,
                    188:   returns number of bytes read, and sets global ttibn to that number and
                    189:   ttibp (the buffer pointer) to zero.
                    190: */
                    191: int
                    192: ttbufr() {                             /* TT Buffer Read */
                    193:     int count;
                    194: 
                    195:     if (ttnet != NET_TCPB) {           /* First make sure current net is */
                    196:        return(-1);                     /* TCP/IP; if not, do nothing. */
                    197:     } else {
                    198:        if (ttibn > 0)                  /* Out internal buffer is not empty, */
                    199:          return(ttibn);                /* so keep using it. */
                    200: #ifdef WINTCP
                    201:        count = 512;                    /* This works for WIN/TCP */
                    202: #else                                  /* Not WINTCP, i.e it's Multinet */
                    203: #ifdef DEC_TCPIP
                    204:        count = 512;                    /* This works for WIN/TCP */
                    205: #else                                  /* Not WINTCP, i.e it's Multinet */
                    206:        count = nettchk();              /* Check network input buffer, */
                    207:        if (ttibn > 0) return(ttibn);   /* which can put a char there! */
                    208:        if (count < 0)                  /* Read error */
                    209:          return(-1);
                    210:        else if (count > TTIBUFL)       /* Too many to read */
                    211:          count = TTIBUFL;
                    212:        else if (count == 0)            /* None, so force blocking read */
                    213:          count = 1;
                    214: #endif /* DEC_TCPIP */
                    215: #endif /* WINTCP */
                    216:        debug(F101,"ttbufr count 1","",count);
                    217: 
                    218: #ifdef COMMENT
                    219: /*
                    220:  This is for nonblocking reads, which we don't do any more.  This code didn't
                    221:  work anyway, in the sense that a broken connection was never sensed.
                    222: */
                    223:        if ((count = socket_read(ttyfd,ttibuf,count)) < 1) {
                    224:            if (count == -1 && socket_errno == EWOULDBLOCK) {
                    225:                debug(F100,"ttbufr finds nothing","",0);
                    226:                return(0);
                    227:            } else if (count == 0) {
                    228:                debug(F100,"ttbufr socket eof","",0);           
                    229:                return(-1);
                    230:            } else {
                    231:                debug(F101,"ttbufr socket_read error","",socket_errno);
                    232:                return(-1);
                    233:            }
                    234:        }
                    235: #else
                    236: /* This is for blocking reads */
                    237:        if ((count = socket_read(ttyfd,ttibuf,count)) < 1) {
                    238:            debug(F101,"ttbufr socket_read","",count);
                    239:            debug(F101,"ttbufr socket_errno","",socket_errno);
                    240:            return(-1);
                    241:        }
                    242: #endif /* COMMENT */
                    243:        ttibp = 0;                      /* Reset buffer pointer. */
                    244:        ttibn = count;
                    245: #ifdef DEBUG
                    246:        debug(F101,"ttbufr count 2","",count); /* Got some bytes. */
                    247:        if (count > 0) ttibuf[count] = '\0';
                    248:        debug(F111,"ttbufr ttibuf",ttibuf,ttibp);
                    249: #endif /* DEBUG */
                    250:        return(ttibn);                  /* Return buffer count. */
                    251:     }
                    252: }
                    253: #endif /* VMSTCPIP */
                    254: 
                    255: /*
                    256:   C-Kermit network open/close functions for BSD-sockets.
                    257:   Much of this code shared by SunLink X.25, which also uses the socket library.
                    258: */
                    259: 
                    260: /*  N E T O P E N  --  Open a network connection.  */
                    261: 
                    262: /*  Returns 0 on success, -1 on failure.  */
                    263: 
                    264: #define        TELNET_PORT     23         /* Should do lookup, but it won't change */
                    265: 
                    266: /* This symbol is not known to, e.g., Ultrix 2.0 */
                    267: #ifndef TELOPT_TTYPE
                    268: #define TELOPT_TTYPE 24
                    269: #endif /* TELOPT_TTYPE */
                    270: 
                    271: /*  N E T O P N  --  Open a network connection.  */
                    272: /*
                    273:   Call with:
                    274:     name of host (or host:service),
                    275:     lcl - local-mode flag to be set if this function succeeds,
                    276:     network type - value defined in ckunet.h.
                    277: */
                    278: 
                    279: #ifdef EXCELAN
                    280: /*
                    281:   Most other BSD sockets implementations define these in header files
                    282:   and libraries.
                    283: */
                    284: struct servent {
                    285:     unsigned short s_port;
                    286: };
                    287: 
                    288: struct hostent {
                    289:     short h_addrtype;
                    290:     struct in_addr h_addr;
                    291:     int h_length;
                    292: };
                    293: 
                    294: struct servent *
                    295: getservbyname(service, connection) char *service,*connection; {
                    296:     static struct servent servrec;
                    297:     int port;
                    298: 
                    299:     port = 0;
                    300:     if (strcmp(service, "telnet") == 0) port = 23;
                    301:     else if (strcmp(service, "smtp") == 0) port = 25;
                    302:     else port = atoi(service);
                    303: 
                    304:     debug(F101,"getservbyname return port ","",port);
                    305: 
                    306:     if (port > 0) {
                    307:        servrec.s_port = htons(port);
                    308:        return( &servrec );
                    309:     }
                    310:     return( (struct servent *) NULL );
                    311: }
                    312: 
                    313: struct hostent *
                    314: gethostbyname(hostname) char *hostname; {
                    315:     return( (struct hostent *) NULL );
                    316: }
                    317: 
                    318: unsigned long
                    319: inet_addr(name) char *name; {
                    320:     unsigned long addr;
                    321: 
                    322:     addr = rhost(&name);
                    323:     debug(F111,"inet_addr ",name,(int)addr);
                    324:     return(addr);
                    325: }
                    326: 
                    327: char *
                    328: inet_ntoa(in) struct in_addr in; {
                    329:     static char name[80];
                    330:     sprintf(name, "%d.%d.%d.%d", in.s_net, in.s_host, in.s_lh, in.s_impno);
                    331:     return(name);
                    332: }
                    333: #endif /* EXCELAN */
                    334: 
                    335: /*  N E T O P E N  --  Open a network connection  */
                    336: /*
                    337:   Calling conventions same as ttopen(), except third argument is network
                    338:   type rather than modem type.  Designed to be called from within ttopen.
                    339: */
                    340: int
                    341: netopen(name, lcl, nett) char *name; int *lcl, nett; {
                    342:     char *p;
                    343: #ifdef SO_OOBINLINE
                    344:     int on = 1;
                    345: #endif /* SO_OOBINLINE */
                    346:     int i, x;
                    347:     struct servent *service, servrec;
                    348:     struct hostent *host;
                    349:     struct sockaddr_in saddr;
                    350: #ifdef EXCELAN
                    351:     struct sockaddr_in send_socket;
                    352: #endif /* EXCELAN */
                    353: 
                    354: #ifdef SUNX25                          /* Code for SunLink X.25 support */
                    355: #define X29PID 1                       /* X.29 Protocol ID */
                    356:     VOID x25oobh();
                    357:     CONN_DB x25host;
                    358:     FACILITY_DB x25facil;
                    359:     static int needh = 1;
                    360:     PID_T pid;
                    361:     extern int linkid, lcn, x25ver;
                    362:     extern int revcall, closgr, cudata;
                    363:     extern char udata[MAXCUDATA];
                    364: #endif /* SUNX25 */
                    365: 
                    366:     debug(F101,"netopen nett","",nett);
                    367:     *ipaddr = '\0';                    /* Initialize IP address string */
                    368: 
                    369: #ifdef SUNX25
                    370:     if (nett == NET_SX25) {            /* If network type is X.25 */
                    371:         netclos();                     /* Close any previous net connection */
                    372:         ttnproto = NP_NONE;            /* No protocol selected yet */
                    373: 
                    374:         /* Set up host structure */
                    375:         bzero ((char *)&x25host,sizeof(x25host));
                    376:         if ((x25host.hostlen = pkx121 (name,x25host.host)) < 0) {
                    377:             fprintf (stderr,"Invalid X.121 host address %s\n",name);
                    378:             errno = 0;
                    379:             return (-1);
                    380:         }
                    381:         x25host.datalen = X29PIDLEN;
                    382:         x25host.data[0] = X29PID;
                    383: 
                    384:        /* Set call user data if specified */
                    385:         if (cudata) {
                    386:             strncpy(x25host.data+X29PIDLEN,udata,(int)strlen(udata));
                    387:             x25host.datalen += (int)strlen(udata);
                    388:         }
                    389: 
                    390:         /* Open SunLink X.25 socket */
                    391:         if ((ttyfd = socket (AF_X25, SOCK_STREAM, 0)) < 0) {
                    392:            debug(F101,"netopen socket error","",errno);
                    393:             perror ("X.25 connect socket error");
                    394:             return (-1);
                    395:         }
                    396: 
                    397:         /* Setting X.25 out-of-band data handler */
                    398:         pid = getpid();
                    399:         if (ioctl(ttyfd,SIOCSPGRP,&pid)) {
                    400:             perror("Setting process group id");
                    401:             return(-1);
                    402:         }
                    403:         (VOID) signal(SIGURG,x25oobh);
                    404: 
                    405:         /* Set reverse charge call and closed user group if requested */
                    406:         bzero ((char *)&x25facil,sizeof(x25facil));
                    407:         if (revcall) x25facil.reverse_charge = revcall;
                    408:         if (closgr > -1) {
                    409:             x25facil.cug_req = 1;
                    410:             x25facil.cug_index = closgr;
                    411:         }
                    412:         if (ioctl(ttyfd,X25_WR_FACILITY,&x25facil) < 0) {
                    413:             perror ("Setting X.25 facilities");
                    414:             return (-1);
                    415:         }
                    416: 
                    417:         /*  Need X.25 header with bits Q and M */
                    418:         if (ioctl (ttyfd,X25_HEADER,&needh) < 0) {
                    419:             perror ("Setting X.25 header");
                    420:             return (-1);
                    421:         }
                    422: 
                    423:         /* Connects to remote host via SunLink X.25 */
                    424:         if (connect(ttyfd,&x25host,sizeof(x25host)) < 0) {
                    425:             debug(F101,"netopen connect errno","",errno);
                    426:             i = errno;
                    427:            if (errno) {
                    428:                 perror("netopen");
                    429:                 x25diag();
                    430:             }
                    431:             (VOID) close (ttyfd);
                    432:             ttyfd = -1;
                    433:             errno = i;
                    434:             return (-1);
                    435:         }
                    436: 
                    437:         /* Get X.25 link identification used for the connection */
                    438:         if (ioctl(ttyfd,X25_GET_LINK,&linkid) < 0) {
                    439:             perror ("Getting X.25 link id");
                    440:             return (-1);
                    441:         }
                    442: 
                    443:         /* Get X.25 logical channel number used for the connection */
                    444:         if (ioctl(ttyfd,X25_RD_LCGN,&lcn) < 0) {
                    445:             perror ("Getting X.25 lcn");
                    446:             return (-1);
                    447:         }
                    448: 
                    449:         /* Get SunLink X.25 version */
                    450:         if (ioctl(ttyfd,X25_VERSION,&x25ver) < 0) {
                    451:             perror ("Getting SunLink X.25 version");
                    452:             return (-1);
                    453:         }
                    454:         ttnet = nett;                   /* Sunlink X.25 network */
                    455:         ttnproto = NP_X3;               /* PAD X.3, X.28, X.29 protocol */
                    456:         if (*lcl < 0) *lcl = 1;         /* Local mode */
                    457:         return(0);
                    458:     } else /* Note that SUNX25 support can coexist with TCP/IP support. */
                    459: #endif /* SUNX25 */
                    460: /*
                    461:   Add support for other networks here.
                    462: */
                    463:     if (nett != NET_TCPB) return(-1);  /* BSD socket support */
                    464: 
                    465:     netclos();                         /* Close any previous connection. */
                    466:     strncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
                    467:     ttnproto = NP_NONE;                        /* No protocol selected yet. */
                    468:     debug(F110,"netopen namecopy",namecopy,0);
                    469: 
                    470:     p = namecopy;                      /* Was a service requested? */
                    471:     while (*p != '\0' && *p != ':') p++; /* Look for colon */
                    472:     if (*p == ':') {                   /* Have a colon */
                    473:        *p++ = '\0';                    /* Get service name or number */
                    474:     } else {                           /* Otherwise use telnet */
                    475:        p = "telnet";
                    476:     }
                    477:     debug(F110,"netopen service requested",p,0);
                    478:     if (isdigit(*p)) {                 /* Use socket number without lookup */
                    479:        service = &servrec;
                    480:        service->s_port = htons((unsigned short)atoi(p));
                    481:     } else {                           /* Otherwise lookup the service name */
                    482:        service = getservbyname(p, "tcp");
                    483:     }
                    484:     if (!service) {
                    485:        fprintf(stderr, "Cannot find port for service %s\n", p);
                    486: #ifdef MULTINET
                    487:        debug(F101,"netopen can't get service","",socket_errno);
                    488: #else
                    489:        debug(F101,"netopen can't get service","",errno);
                    490: #endif /* MULTINET */
                    491:        errno = 0;                      /* rather than mislead */
                    492:        return(-1);
                    493:     }
                    494:     /* Set up socket structure and get host address */
                    495: 
                    496:     bzero((char *)&saddr, sizeof(saddr));
                    497:     if ((host = gethostbyname(namecopy)) != NULL) {
                    498:        saddr.sin_family = host->h_addrtype;
                    499:        bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
                    500:     } else {
                    501: #ifdef INADDRX
                    502: /* inet_addr() is of type struct in_addr */
                    503:        struct in_addr ina;
                    504:        unsigned long uu;
                    505: #ifdef datageneral
                    506:         extern struct in_addr inet_addr();
                    507: #endif /* datageneral */
                    508:        ina = inet_addr(namecopy);
                    509:        uu = *(unsigned long *)&ina;
                    510: #else /* Not INADDRX */
                    511: /* inet_addr() is unsigned long */
                    512:        unsigned long uu;
                    513:        uu = inet_addr(namecopy);
                    514: #endif /* INADDRX */
                    515:        if ((saddr.sin_addr.s_addr = uu) != ((unsigned long)-1))
                    516:          saddr.sin_family = AF_INET;
                    517:        else {
                    518:          fprintf(stderr, "Can't get address for %s\n", namecopy);
                    519: #ifdef MULTINET
                    520:          debug(F101,"netopen can't get address","",socket_errno);
                    521: #else
                    522:          debug(F101,"netopen can't get address","",errno);
                    523: #endif /* MULTINET */
                    524:          errno = 0;                    /* rather than mislead */
                    525:          return(-1);
                    526:       }
                    527:     }
                    528: 
                    529:     /* Get a file descriptor for the connection. */
                    530: 
                    531:     saddr.sin_port = service->s_port;
                    532:     sprintf(ipaddr,"%s", inet_ntoa(saddr.sin_addr));
                    533:     if (!quiet && *ipaddr) printf(" Trying %s...\n", ipaddr);
                    534: 
                    535: #ifdef EXCELAN
                    536:     send_socket.sin_family = AF_INET;
                    537:     send_socket.sin_addr.s_addr = 0;
                    538:     send_socket.sin_port = 0;
                    539:     if ((ttyfd = socket(SOCK_STREAM, (struct sockproto *)0,
                    540:                &send_socket, SO_REUSEADDR)) < 0)
                    541: #else
                    542:     if ((ttyfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
                    543: #endif /* EXCELAN */
                    544:       {
                    545: #ifdef EXCELAN
                    546:        experror("TCP socket error");
                    547: #else
                    548: #ifdef MULTINET
                    549:        socket_perror("TCP socket error");
                    550:        debug(F101,"netopen socket error","",socket_errno);
                    551: #else
                    552:        perror("TCP socket error");
                    553:        debug(F101,"netopen socket error","",errno);
                    554: #endif /* MULTINET */
                    555: #endif /* EXCELAN */
                    556:        return (-1);
                    557:     }
                    558:     errno = 0;
                    559: 
                    560:     /* Now connect to the socket on the other end. */
                    561: 
                    562: #ifdef EXCELAN
                    563:     if (connect(ttyfd, &saddr) < 0)
                    564: #else
                    565:     if (connect(ttyfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
                    566: #endif /* EXCELAN */
                    567:       {
                    568:        i = errno;                      /* save error code */
                    569:        close(ttyfd);
                    570:        ttyfd = -1;
                    571:        errno = i;                      /* and report this error */
                    572: #ifdef EXCELAN
                    573:        if (errno) experror("netopen connect");
                    574: #else
                    575: #ifdef MULTINET
                    576:        debug(F101,"netopen connect error","",socket_errno);
                    577:        if (errno) socket_perror("netopen connect");
                    578: #else
                    579:        debug(F101,"netopen connect errno","",errno);
                    580: #ifdef WINTCP
                    581:        perror("netopen connect");
                    582: #endif /* WINTCP */
                    583: #ifdef DEC_TCPIP
                    584:        perror("netopen connect");
                    585: #endif /* DEC_TCPIP */
                    586: #endif /* MULTINET */
                    587: #endif /* EXCELAN */
                    588:        return(-1);
                    589:     }
                    590: #ifdef SO_OOBINLINE
                    591: /*
                    592:   The symbol SO_OOBINLINE is not known to Ultrix 2.0.
                    593:   It means "leave out of band data inline".  The normal value is 0x0100,
                    594:   but don't try this on systems where the symbol is undefined.
                    595: */
                    596: #ifdef datageneral
                    597:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
                    598: #else
                    599: #ifdef BSD43
                    600:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
                    601: #else
                    602: #ifdef OSF1
                    603:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
                    604: #else
                    605: #ifdef POSIX
                    606:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
                    607: #else
                    608: #ifdef SOLARIS
                    609: /*
                    610:   Maybe this applies to all SVR4 versions, but the other (else) way has been
                    611:   compiling and working fine on all the others, so best not to change it.
                    612: */
                    613:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
                    614: #else
                    615:     setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
                    616: #endif /* SOLARIS */
                    617: #endif /* POSIX */
                    618: #endif /* BSD43 */
                    619: #endif /* OSF1 */
                    620: #endif /* datageneral */
                    621: #endif /* SO_OOBINLINE */
                    622: 
                    623:     /* See if the service is TELNET. */
                    624:     if ((x = ntohs((unsigned short)service->s_port)) == TELNET_PORT)
                    625:       ttnproto = NP_TELNET;            /* Yes, set global flag. */
                    626:     debug(F101,"netopen service","",x);
                    627:     ttnet = nett;                      /* TCP/IP (sockets) network */
                    628:     tn_init = 0;                       /* Telnet protocol not init'd yet */
                    629:     if (*lcl < 0) *lcl = 1;            /* Local mode. */
                    630:     return(0);                         /* Done. */
                    631: }
                    632: 
                    633: /*  N E T C L O S  --  Close current network connection.  */
                    634: 
                    635: int
                    636: netclos() {
                    637:     int x = 0;
                    638:     if (ttyfd < 0)                     /* Was open? */
                    639:       return(0);                       /* Wasn't. */
                    640:     if (ttyfd > -1)                    /* Was. */
                    641: #ifdef VMSTCPIP
                    642:       x = socket_close(ttyfd);         /* Close it. */
                    643: #else
                    644:       x = close(ttyfd);
                    645: #endif /* VMSTCPIP */
                    646:     ttyfd = -1;                                /* Mark it as closed. */
                    647:     tn_init = 0;                       /* Remember about telnet protocol... */
                    648:     *ipaddr = '\0';                    /* Zero the IP address string */
                    649:     return(x);
                    650: }
                    651: 
                    652: /*  N E T T C H K  --  Check if network up, and how many bytes can be read */
                    653: /*
                    654:   Returns number of bytes waiting, or -1 if connection has been dropped.
                    655: */
                    656: int                                    /* Check how many bytes are ready */
                    657: nettchk() {                            /* for reading from network */
                    658: #ifdef VMSTCPIP
                    659:     unsigned int count;
                    660:     int x, y;
                    661:     char c;
                    662: 
                    663:     debug(F101,"nettchk entry ttibn","",ttibn);
                    664:     debug(F101,"nettchk entry ttibp","",ttibp);
                    665:     socket_errno = 0;
                    666: /*
                    667:   Note: this socket_ioctl() call does NOT return an error if the
                    668:   connection has been broken.  (At least not in Multinet.)
                    669: */
                    670:     if (socket_ioctl(ttyfd,FIONREAD,&count) < 0) {
                    671:        debug(F101,"nettchk socket_ioctl error","",socket_errno);
                    672:        if (ttibn < 1) return(-1);
                    673:        else return(ttibn);
                    674:     }
                    675:     debug(F101,"nettchk count","",count);
                    676: 
                    677: #ifndef DEC_TCPIP
                    678: /*
                    679:   Let's see if we can skip this for UCX, since it seems to cause trouble.
                    680: */
                    681:     if (count == 0) {
                    682: /*
                    683:   Here we need to tell the difference between a 0 count on an active
                    684:   connection, and a 0 count because the remote end of the socket broke the
                    685:   connection.  There is no mechanism in TGV MultiNet (or WIN/TCP?) to query
                    686:   the status of the connection, so we have to do a read.  -1 means there was
                    687:   no data available (socket_errno == EWOULDBLOCK), 0 means the connection is
                    688:   down.  But if, by chance, we actually get a character, we have to put it
                    689:   where it won't be lost.
                    690: */
                    691:        y = 1;                          /* Turn on nonblocking reads */
                    692:        debug(F101,"nettchk before FIONBIO","",x);
                    693:        x = socket_ioctl(ttyfd,FIONBIO,&y);
                    694:        debug(F101,"nettchk FIONBIO","",x);
                    695:        x = socket_read(ttyfd,&c,1);    /* Returns -1 if no data */
                    696:        debug(F101,"nettchk socket_read","",x);
                    697:        y = 0;                          /* Turn them back off */
                    698:        socket_ioctl(ttyfd,FIONBIO,&y);
                    699:        if (x == 0) return(-1);         /* Connection is broken. */
                    700:        if (x == 1) {                   /* Oops, actually got a byte? */
                    701:            debug(F101,"nettchk socket_read char","",c);
                    702:            debug(F101,"nettchk ttibp","",ttibp);
                    703:            debug(F101,"nettchk ttibn","",ttibn);
                    704: /*
                    705:   So put the byte we got into the buffer at the current position.
                    706:   Increment the buffer count, but DON'T increment the buffer pointer.
                    707: */
                    708:            ttibuf[ttibp+ttibn] = c;
                    709:            ttibn++;
                    710: #ifdef DEBUG
                    711:            ttibuf[ttibp+ttibn] = '\0';
                    712:            debug(F111,"nettchk ttibn",ttibuf,ttibn);
                    713: #endif /* DEBUG */
                    714:        }
                    715:     }
                    716: #endif /* DEC_TCPIP */
                    717:     debug(F101,"nettchk returns","",count+ttibn);
                    718:     return(count + ttibn);
                    719: 
                    720: #else /* Not VMSTCPIP */
                    721: /*
                    722:   UNIX just uses ttchk(), in which the ioctl() calls on the file descriptor
                    723:   seem to work OK.
                    724: */
                    725:     return(0);
                    726: #endif /* VMSTCPIP */
                    727: /*
                    728:   But what about X.25?
                    729: */
                    730: }
                    731: 
                    732: /*  N E T I N C --  Input character from network */
                    733: 
                    734: int                    
                    735: netinc(timo) int timo; {
                    736: #ifdef VMSTCPIP
                    737:     int x; unsigned char c;            /* The locals. */
                    738: 
                    739:     if (ttibn > 0) {                   /* Something in internal buffer? */
                    740:        debug(F100,"netinc char in buf","",0); /* Yes. */
                    741:        x = 0;                          /* Success. */
                    742:     } else {                           /* Else must read from network. */
                    743:        x = -1;                         /* Assume failure. */
                    744: #ifdef DEBUG
                    745:        debug(F101,"netinc goes to net, timo","",timo);
                    746:        ttibuf[ttibp+1] = '\0';
                    747:        debug(F111,"netinc ttibuf",ttibuf,ttibp);
                    748: #endif /* DEBUG */
                    749:        if (timo <= 0) {                /* Untimed case. */
                    750:            while (1) {                 /* Wait forever if necessary. */
                    751:                if (ttbufr() < 0)       /* Refill buffer. */
                    752:                  break;                /* Error, fail. */
                    753:                if (ttibn > 0) {        /* Success. */
                    754:                    x = 0;
                    755:                    break;
                    756:                }
                    757:            }
                    758:        } else {                        /* Timed case... */
                    759:            saval = signal(SIGALRM,ttimoff); /* Enable timer interrupt */
                    760:            alarm(timo);                /* for requested interval. */
                    761:            if (setjmp(njbuf)) {        /* Timer went off? */
                    762:                x = -1;                 /* Yes, fail. */
                    763:            } else {
                    764:                while (1) {
                    765:                    if (ttbufr() < 0)   /* Keep trying to refill it. */
                    766:                      break;            /* Till we get an error. */
                    767:                    if (ttibn > 0) {    /* Or we get a character. */
                    768:                        x = 0;
                    769:                        break;
                    770:                    }
                    771:                }
                    772:            }
                    773:            ttimoff();                  /* Timer off. */
                    774:        }
                    775:     }
                    776:     if (x < 0) {                       /* Return -1 if we failed. */
                    777:        debug(F100,"netinc timed out","",0);
                    778:        return(-1);
                    779:     } else {                           /* Otherwise */
                    780:        ttibn--;                        /* Return what we got. */
                    781:        c = ttibuf[ttibp++];
                    782:        debug(F101,"netinc returning","",c);
                    783:        return((c & 0xff));
                    784:     }
                    785: #else /* Not MULTINET or WINTCP */
                    786:     return(-1);
                    787: #endif /* VMSTCPIP */
                    788: }
                    789: 
                    790: /*  N E T T O L  --  Output a string of bytes to the network  */
                    791: /*
                    792:   Call with s = pointer to string, n = length.
                    793:   Returns number of bytes actually written on success, or
                    794:   -1 on i/o error, -2 if called improperly.
                    795: */
                    796: int
                    797: nettol(s,n) char *s; int n; {
                    798: #ifdef VMSTCPIP
                    799:     int count;
                    800:     if (ttnet == NET_TCPB) {
                    801:        if ((count = socket_write(ttyfd,s,n)) < 1) {
                    802:            debug(F101,"nettol socket_write error","",socket_errno);
                    803:            return(-1);
                    804:        }
                    805:        debug(F111,"nettol socket_write",s,count);
                    806:        return(count);
                    807:     } else return(-2);
                    808: #else
                    809:     debug(F100,"nettol VMSTCPIP not defined","",0);
                    810:     return(-2);
                    811: #endif /* VMSTCPIP */
                    812: }
                    813: 
                    814: /*  N E T T O C  --   Output character to network */
                    815: /*
                    816:   Call with character to be transmitted.
                    817:   Returns 0 if transmission was successful, or
                    818:   -1 upon i/o error, or -2 if called improperly.
                    819: */
                    820: int                    
                    821: #ifdef CK_ANSIC
                    822: nettoc(char c)
                    823: #else
                    824: nettoc(c) char c;
                    825: #endif /* CK_ANSIC */
                    826: /* nettoc */ {
                    827: #ifdef VMSTCPIP
                    828:     unsigned char cc;
                    829:     cc = c;
                    830:     if (ttnet == NET_TCPB) {
                    831:        debug(F101,"nettoc cc","",cc);
                    832:        if (socket_write(ttyfd,&cc,1) < 1) {
                    833:            debug(F101,"nettoc socket_write error","",socket_errno);
                    834:            return(-1);
                    835:        }
                    836:        debug(F101,"nettoc socket_write","", cc);
                    837:        return(0);
                    838:     } else return(-2);
                    839: #else
                    840:     return(-2);
                    841: #endif /* MULTINET */
                    842: }
                    843: 
                    844: /*  N E T F L U I  --  Flush network input buffer  */
                    845: 
                    846: int
                    847: netflui() {
                    848:     int n;
                    849: #ifdef VMSTCPIP
                    850:     ttibuf[ttibp+1] = '\0';
                    851:     debug(F111,"netflui 1",ttibuf,ttibn);
                    852:     ttibn = ttibp = 0;                 /* Flush internal buffer *FIRST* */
                    853:     if ((n = nettchk()) > 0) {         /* Now see what's waiting on the net */
                    854:        if (n > TTIBUFL) n = TTIBUFL;   /* and sponge it up */
                    855:        debug(F101,"netflui 2","",n);   /* ... */
                    856:        n = socket_read(ttyfd,ttibuf,n) ; /* into our buffer */
                    857:        if (n >= 0) ttibuf[n] = '\0';
                    858:        debug(F111,"netflui 3",ttibuf,n);
                    859:        ttibuf[0] = '\0';
                    860:     }
                    861: #else
                    862: /*
                    863:   It seems the UNIX ioctl()s don't do the trick, so we have to read the
                    864:   stuff ourselves.  This should be pretty much portable, if not elegant.
                    865: */
                    866:     if ((n = ttchk()) > 0) {
                    867:        debug(F101,"netflui","",n);
                    868:        while ((n--) && ttinc(0) > -1) ; /* Don't worry, it's buffered. */
                    869:     }
                    870: #endif /* VMSTCPIP */
                    871:     return(0);
                    872: }
                    873: 
                    874: #ifdef TNCODE                          /* Compile in telnet support code */
                    875: 
                    876: /* TCP/IP Telnet negotiation support code */
                    877: 
                    878: static int sgaflg = 0;                 /* telnet SGA flag */
                    879: static int wttflg = 0;                 /* telnet terminal type flag */
                    880: 
                    881: #ifndef TELCMDS
                    882: char *telcmds[] = {
                    883:     "SE", "NOP", "DMARK", "BRK",  "IP",   "AO", "AYT",  "EC",
                    884:     "EL", "GA",  "SB",    "WILL", "WONT", "DO", "DONT", "IAC",
                    885: };
                    886: int ntelcmds = sizeof(telcmds) / sizeof(char *);
                    887: #endif /* TELCMDS */
                    888: 
                    889: #ifndef TELOPTS
                    890: char *telopts[] = {
                    891:        "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
                    892:        "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
                    893:        "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
                    894:        "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
                    895:        "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
                    896:        "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD"
                    897: #ifdef TELOPT_TUID
                    898:        ,"TACACS UID"
                    899: #ifdef TELOPT_OUTMRK
                    900:        ,"OUTPUT MARKING"
                    901: #ifdef TELOPT_TTYLOC
                    902:        ,"TTYLOC"
                    903: #ifdef TELOPT_3270REGIME
                    904:        ,"3270 REGIME"
                    905: #ifdef TELOPT_X3PAD
                    906:        ,"X.3 PAD"
                    907: #ifdef TELOPT_NAWS
                    908:        ,"NAWS"
                    909: #ifdef TELOPT_TSPEED
                    910:        ,"TSPEED"
                    911: #ifdef TELOPT_LFLOW
                    912:        ,"LFLOW"
                    913: #ifdef TELOPT_LINEMODE
                    914:        ,"LINEMODE"
                    915: #endif
                    916: #endif
                    917: #endif
                    918: #endif
                    919: #endif
                    920: #endif
                    921: #endif
                    922: #endif
                    923: #endif
                    924: };
                    925: #endif /* TELOPTS */
                    926: 
                    927: int ntelopts = sizeof(telopts) / sizeof(char *);
                    928: #endif /* TNCODE */
                    929: 
                    930: 
                    931: /* Send network BREAK */
                    932: /*
                    933:   Returns -1 on error, 0 if nothing happens, 1 if BREAK sent successfully.
                    934: */
                    935: int
                    936: netbreak() {
                    937:     CHAR buf[3];
                    938:     if (ttnet == NET_TCPB) {
                    939:        if (ttnproto == NP_TELNET) {
                    940: #ifdef TNCODE
                    941:            buf[0] = (CHAR) IAC; buf[1] = (CHAR) BREAK;
                    942:            if (ttol(buf,2) < 2) return(-1);
                    943:            debug(F101,"telnet BREAK ok","",BREAK);
                    944:            return(1);
                    945: #else
                    946:            debug(F100,"netbreak no TNCODE","",0);
                    947:            return(0);
                    948: #endif /* TNCODE */
                    949:        }
                    950:        /* Insert other TCP/IP protocols here */
                    951:     }
                    952:     /* Insert other networks here */
                    953:     return(0);
                    954: }
                    955: 
                    956: /* Send a telnet option, avoid loops. */
                    957: /* Returns 1 if command was sent, 0 if not, -1 on error */
                    958: 
                    959: int
                    960: tn_sopt(cmd,opt) int cmd, opt; {       /* TELNET SEND OPTION */
                    961:     CHAR buf[4];
                    962:     int n;
                    963:     if (ttnet != NET_TCPB) return(0);  /* Must be TCP/IP */
                    964:     if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
                    965:     n = cmd - SE;
                    966:     if (n < 0 || n > ntelcmds) return(0);
                    967: #ifdef TNCODE
                    968:     buf[0] = (CHAR) IAC;
                    969:     buf[1] = (CHAR) cmd & 0xff;
                    970:     buf[2] = (CHAR) opt & 0xff;
                    971:     if (ttol(buf,3) < 3)
                    972:       return(-1);
                    973:     debug(F111,"telnet cmd >",telcmds[n],cmd);
                    974:     debug(F111,"telnet opt >",
                    975:          (opt < ntelopts) ? telopts[opt] : "UNKNOWN", opt );
                    976:     if (debses && cmd != SB)
                    977:       printf("[%s %s]",telcmds[n],
                    978:             (opt < ntelopts) ? telopts[opt] : "UNKNOWN");
                    979:     return(1);
                    980: #else
                    981:     debug(F100,"tn_sopt no TNCODE","",0);
                    982:     return(0);
                    983: #endif /* TNCODE */
                    984: }
                    985: 
                    986: /* Initialize a telnet connection. */
                    987: /* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
                    988: 
                    989: int
                    990: tn_ini() {
                    991: #ifndef TNCODE
                    992:     debug(F100,"tn_ini no TNCODE","",0);
                    993:     return(0);
                    994: #else /* TELNET protocol support */
                    995:     debug(F101,"tn_ini ttnproto","",ttnproto);
                    996:     debug(F101,"tn_ini tn_init","",tn_init);
                    997: 
                    998:     if (ttnet != NET_TCPB)             /* Make sure connection is TCP/IP. */
                    999:       return(0);
                   1000:     if (tn_init)                       /* Have we done this already? */
                   1001:       return(0);                       /* Don't do it again. */
                   1002:     debug(F101,"tn_ini tn_duplex","",tn_duplex);
                   1003:     duplex = tn_duplex;                        /* Assume local echo. */
                   1004:     sgaflg = 0;                                /* Assume Go-Ahead suppressed. */
                   1005:     wttflg = 0;                                /* Did not send WILL TERM TYPE yet. */
                   1006:     if (ttnproto == NP_NONE) {         /* If not talking to a telnet port, */
                   1007:        ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
                   1008:        tn_init = 1;                    /* but don't send initial options. */
                   1009:        debug(F100,"tn_ini skipping telnet negotiations","",0);
                   1010:        return(0);
                   1011:     }
                   1012:     /* Talking to telnet port, so send WILL TERMINAL TYPE and DO SGA */
                   1013: 
                   1014:     if (tn_sopt(WILL,TELOPT_TTYPE) < 0)        /* Will send terminal type. */
                   1015:       return(-1);
                   1016:     wttflg = 1;                                /* Remember I said I would. */
                   1017:     if (tn_sopt(DO,TELOPT_SGA) < 0)    /* Please suppress go-ahead. */
                   1018:       return(-1);
                   1019: #ifdef COMMENT
                   1020:     if (tn_sopt(DO,TELOPT_ECHO) < 0)   /* Ask the server to echo, since */
                   1021:       return(-1);                      /* I'm assuming it will. */
                   1022: #endif /* COMMENT */
                   1023:     tn_init = 1;                       /* Set telnet-initialized flag. */
                   1024: 
                   1025:     /* Don't send anthing else! */
                   1026: 
                   1027:     debug(F101,"tn_ini duplex","",duplex);
                   1028:     return(1);
                   1029: #endif /* TNCODE */
                   1030: }
                   1031: 
                   1032: /*
                   1033:   Process in-band Telnet negotiation characters from the remote host.
                   1034:   Call with the telnet IAC character and the current duplex setting
                   1035:   (0 = remote echo, 1 = local echo).
                   1036:   Returns:
                   1037:     3 if server has sent us a quoted IAC
                   1038:     2 if local echo must be changed to remote
                   1039:     1 if remote echo must be changed to local
                   1040:     0 if nothing happens or no action necessary
                   1041:    -1 on failure (= internal or i/o error)
                   1042: */
                   1043: 
                   1044: #define TSBUFSIZ 41
                   1045: char sb[TSBUFSIZ];                     /* Buffer for subnegotiations */
                   1046: 
                   1047: int
                   1048: #ifdef CK_ANSIC                                /* TELNET DO OPTION */
                   1049: tn_doop( CHAR z, int echo, int (*fn)(int) )
                   1050: #else
                   1051: tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
                   1052: #endif /* CK_ANSIC */
                   1053: /* tn_doop */ {
                   1054:     int c, x, y, n, m, flag;
                   1055: 
                   1056: #ifndef TNCODE
                   1057:     debug(F100,"tn_doop no TNCODE","",0);
                   1058:     return(0);
                   1059: #else
                   1060:     if (z != (CHAR) IAC) {
                   1061:        debug(F101,"tn_doop bad call","",z);
                   1062:        return(-1);
                   1063:     }
                   1064:     if (ttnet != NET_TCPB) return(0);
                   1065:     if (ttnproto != NP_TELNET) return(0);      /* Check protocol */
                   1066: 
                   1067: /* Have IAC, read command character. */
                   1068: 
                   1069:     c = (*fn)(0) & 0xff;               /* Read command character */
                   1070:     m = c - SE;                                /* Check validity */
                   1071:     if (m < 0 || m > ntelcmds) {
                   1072:        debug(F101,"tn_doop bad cmd","",c);
                   1073:        return(0);
                   1074:     }
                   1075:     if (seslog) {                      /* Copy to session log, if any. */
                   1076:        if (zchout(ZSFILE, (char) z) < 0) seslog = 0; /* Log IAC. */
                   1077:        else if (zchout(ZSFILE, (char) c) < 0) seslog = 0; /* Log command */
                   1078:     }
                   1079:     debug(F111,"telnet cmd <",telcmds[m],c); /* Debug log. */
                   1080: 
                   1081:     if (c == (CHAR) IAC) return(3);    /* Quoted IAC */
                   1082:     if (c < SB) return(0);             /* Other command with no arguments. */
                   1083: 
                   1084: /* SB, WILL, WONT, DO, or DONT need more bytes... */
                   1085: 
                   1086:     if ((x = (*fn)(0)) < 0) return(-1);        /* Get the option. */
                   1087:     x &= 0xff;                         /* Trim to 8 bits. */
                   1088: 
                   1089:     debug(F111,"telnet opt <",
                   1090:          (x < ntelopts) ? telopts[x] : "UNKNOWN", x );
                   1091:     if (seslog)                                /* Session log */
                   1092:       if (zchout(ZSFILE, (char) x) < 0) seslog = 0;
                   1093: 
                   1094:     /* Now handle the command */
                   1095: 
                   1096:     if (debses && c != SB)             /* Debug to screen. */
                   1097:       printf("<%s %s>",telcmds[m],
                   1098:             (x < ntelopts) ? telopts[x] : "UNKNOWN" );
                   1099:     switch (x) {
                   1100:       case TELOPT_ECHO:                        /* ECHO negotiation. */
                   1101:        switch (c) {                    /* Command */
                   1102:          case WILL:                    /* Host says it will echo. */
                   1103:            if (echo)                   /* Only reply if change required. */
                   1104:              return((tn_sopt(DO,x) < 0) ? -1 : 2); /* Please do. */
                   1105:            else return(0);             /* Otherwise no change. */
                   1106:          case WONT:                    /* Host says it won't echo. */
                   1107:            if (!echo)                  /* If I'm full duplex */
                   1108:              return ((tn_sopt(DONT,x) < 0) ? -1 : 1); /* Switch to half */
                   1109:            else return(0);             /* Otherwise, no change.  */
                   1110:          case DO:                      /* Host wants me to echo */
                   1111:            if (tn_sopt(WONT,x) < 0)    /* but the client never echoes */
                   1112:              return(-1);               /* back to the server. */
                   1113:          default:                      /* Don't reply to anything else */
                   1114:            return(0);
                   1115:        }
                   1116: 
                   1117:       case TELOPT_SGA:                 /* Suppress Go-Ahead */
                   1118:        switch (c) {                    /* Command... */
                   1119:          case WONT:                    /* Host says it won't. */
                   1120:            if (!sgaflg) {
                   1121:                sgaflg = 1;             /* Remember. */
                   1122:                if (tn_sopt(DONT,x) < 0) /* acknowledge, */
                   1123:                  return(-1);
                   1124:            }
                   1125:            return(echo ? 0 : 1);       /* Switch to half duplex */
                   1126:          case WILL:                    /* Server says it will SGA */
                   1127:            if (sgaflg) {               /* ACK only if necessary */
                   1128:                if (tn_sopt(DO,x) < 0)
                   1129:                  return(-1);
                   1130:                sgaflg = 0;             /* Remember new SGA state. */
                   1131:            }
                   1132:            return(0);                  /* But don't change echo state. */
                   1133:        }
                   1134: 
                   1135: #ifdef TELOPT_TTYPE
                   1136:       case TELOPT_TTYPE:               /* Terminal Type */
                   1137:        switch (c) {
                   1138:          case DO:                      /* DO terminal type. */
                   1139:            if (wttflg == 0) {          /* If I haven't said so before, */
                   1140:                if (tn_sopt((CHAR)WILL,x) < 0) /* say I'll send it if asked. */
                   1141:                  return(-1);
                   1142:                wttflg++;
                   1143:            }
                   1144:            return(0);
                   1145:          case SB:
                   1146:            debug(F100,"TELNET subnegotiation:","",0);
                   1147:            n = flag = 0;               /* Flag for when done reading SB */
                   1148:            while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
                   1149:                if ((y = (*fn)(0)) < 0) /* Read a byte */
                   1150:                  return(-1);
                   1151:                y &= 0xff;              /* Make sure it's just 8 bits. */
                   1152:                sb[n++] = y;            /* Deposit in buffer. */
                   1153:                if (seslog)             /* Take care of session log */
                   1154:                  if (zchout(ZSFILE, (char) y) < 0)
                   1155:                    seslog = 0;
                   1156:                if (y == IAC) {         /* If this is an IAC */
                   1157:                    if (flag) {         /* If previous char was IAC */
                   1158:                        n--;            /* it's quoted, keep one IAC */
                   1159:                        flag = 0;       /* and turn off the flag. */
                   1160:                    } else flag = 1;    /* Otherwise set the flag. */
                   1161:                } else if (flag) {      /* Something else following IAC */
                   1162:                    if (y != SE)        /* If not SE, it's a protocol error */
                   1163:                      flag = 0;
                   1164:                    break;
                   1165:                }
                   1166:            }
                   1167:            if (!flag) {                /* Make sure we got a valid SB */
                   1168:                debug(F100, "TELNET Subnegotian prematurely broken", "",0);
                   1169:                return(-1);
                   1170:            }
                   1171:            if (debses) {               /* Debug to screen. */
                   1172:                int i;
                   1173:                printf("<SB %s ",telopts[TELOPT_TTYPE]);
                   1174:                for (i = 0; i < n-2; i++) printf("%02x",sb[i]);
                   1175:                printf(" IAC SE>");
                   1176:            }
                   1177:            debug(F101,"TELNET suboption<","",sb[0]);
                   1178:            if (sb[0] == 1) {           /* SEND terminal type? */
                   1179:                if (tn_sttyp() < 0)     /* Yes, so send it. */
                   1180:                  return(-1);
                   1181:            }
                   1182:          default:                      /* Others, ignore */
                   1183:            return(0);
                   1184:        }
                   1185: #endif /* TELOPT_TTYPE */
                   1186: 
                   1187:       default:                         /* All others: refuse */
                   1188:        switch(c) {
                   1189:          case WILL:                    /* You will? */
                   1190:            if (tn_sopt(DONT,x) < 0)    /* Please don't. */
                   1191:              return(-1);               /* (Could this cause a loop?) */
                   1192:            break;
                   1193:          case DO:                      /* You want me to? */
                   1194:            if (tn_sopt(WONT,x) < 0)    /* I won't. */
                   1195:              return(-1);
                   1196:            break;
                   1197:          case DONT:                    /* You don't want me to? */
                   1198:            if (tn_sopt(WONT,x) < 0)    /* I won't. */
                   1199:              return(-1);               /* (Could this cause a loop?) */
                   1200:          case WONT:                    /* You won't? */
                   1201:            break;                      /* I didn't want you to. */
                   1202:        }                               /* Anything else, treat as user data */
                   1203:        return(0);
                   1204:     }
                   1205: #endif /* TNCODE */
                   1206: }
                   1207: 
                   1208: /* Telnet send terminal type */
                   1209: /* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
                   1210: 
                   1211: int
                   1212: tn_sttyp() {                           /* Send telnet terminal type. */
                   1213: #ifndef TNCODE
                   1214:     debug(F100,"tn_sttyp no TNCODE","",0);
                   1215:     return(0);
                   1216: #else
                   1217:     char *ttn; int ttl, i;             /* Name & length of terminal type. */
                   1218: 
                   1219:     if (ttnet != NET_TCPB) return(0);
                   1220:     if (ttnproto != NP_TELNET) return(0);
                   1221: 
                   1222:     ttn = NULL;
                   1223: 
                   1224:     if (tn_term) {                     /* Terminal type override? */
                   1225:        debug(F110,"tn_sttyp",tn_term,0);
                   1226:        if (*tn_term) ttn = tn_term;
                   1227:     } else debug(F100,"tn_sttyp no term override","",0);
                   1228: #ifndef datageneral
                   1229:     if (!ttn)                          /* If no override, */
                   1230:       ttn = getenv("TERM");            /* get it from the environment. */
                   1231: #endif /* datageneral */
                   1232:     if ((ttn == ((char *)0)) || ((ttl = (int)strlen(ttn)) >= TSBUFSIZ)) {
                   1233:        ttn = "UNKNOWN";
                   1234:        ttl = 7;
                   1235:     }
                   1236:     sb[0] = IAC;                       /* I Am a Command */
                   1237:     sb[1] = SB;                                /* Subnegotiation */
                   1238:     sb[2] = TELOPT_TTYPE;              /* Terminal Type */
                   1239:     sb[3] = (CHAR) 0;                  /* Is... */
                   1240:     for (i = 4; *ttn; ttn++,i++)       /* Copy and uppercase it */
                   1241:       sb[i] = (islower(*ttn)) ? toupper(*ttn) : *ttn;
                   1242:     ttn = sb;                          /* Point back to beginning */
                   1243:     sb[i++] = IAC;                     /* End of Subnegotiation */
                   1244:     sb[i++] = SE;                      /* marked by IAC SE */
                   1245:     if (ttol((CHAR *)sb,i) < 0)                /* Send it. */
                   1246:       return(-1);
                   1247: #ifdef DEBUG
                   1248:     sb[i-2] = '\0';                    /* For debugging */
                   1249:     debug(F111,"telnet SB sent ttype",sb+4,ttl);
                   1250: #endif /* DEBUG */
                   1251:     if (debses)                                /* Debug to screen. */
                   1252:       printf("[SB TERMINAL TYPE 00 %s IAC SE]",sb+4);
                   1253:     return(1);
                   1254: #endif /* TNCODE */
                   1255: }
                   1256: 
                   1257: #ifdef SUNX25
                   1258: /*
                   1259:   SunLink X.25 support by Marcello Frutig, Catholic University,
                   1260:   Rio de Janeiro, Brazil, 1990.
                   1261: */
                   1262: 
                   1263: /* PAD X.3, X.28 and X.29 support */
                   1264: 
                   1265: static CHAR x29err [MAXPADPARMS+3] = { X29_ERROR, INVALID_PAD_PARM, '\0' };
                   1266: 
                   1267: 
                   1268: /* Initialize PAD */
                   1269: 
                   1270: extern CHAR padparms[MAXPADPARMS+1];
                   1271: 
                   1272: VOID
                   1273: initpad() {
                   1274:   padparms[PAD_BREAK_CHARACTER]        = 0;  /* Break character */
                   1275:   padparms[PAD_ESCAPE]                 = 1;  /* Escape permitted */
                   1276:   padparms[PAD_ECHO]                   = 1;  /* Kermit PAD does echo */
                   1277:   padparms[PAD_DATA_FORWARD_CHAR]      = 2;  /* forward character CR */
                   1278:   padparms[PAD_DATA_FORWARD_TIMEOUT]   = 0;  /* no timeout forward condition */
                   1279:   padparms[PAD_FLOW_CONTROL_BY_PAD]    = 0;  /* not used */
                   1280:   padparms[PAD_SUPPRESSION_OF_SIGNALS] = 1;  /* allow PAD service signals */
                   1281:   padparms[PAD_BREAK_ACTION]           = 21; /* brk action: INT pk + brk ind*/
                   1282:   padparms[PAD_SUPPRESSION_OF_DATA]    = 0;  /* no supression of user data */
                   1283:   padparms[PAD_PADDING_AFTER_CR]       = 0;  /* no padding after CR */
                   1284:   padparms[PAD_LINE_FOLDING]           = 0;  /* no line fold */
                   1285:   padparms[PAD_LINE_SPEED]             = 0;  /* line speed - don't care */
                   1286:   padparms[PAD_FLOW_CONTROL_BY_USER]   = 0;  /* flow cont of PAD - not used */
                   1287:   padparms[PAD_LF_AFTER_CR]            = 0;  /* no LF insertion after CR */
                   1288:   padparms[PAD_PADDING_AFTER_LF]       = 0;  /* no padding after LF */
                   1289:   padparms[PAD_EDITING]                = 1;  /* can edit */
                   1290:   padparms[PAD_CHAR_DELETE_CHAR]       = 8;  /* character delete character */
                   1291:   padparms[PAD_BUFFER_DELETE_CHAR]     = 21; /* buffer delete character */
                   1292:   padparms[PAD_BUFFER_DISPLAY_CHAR]    = 18; /* buffer display character */
                   1293: }
                   1294: 
                   1295: 
                   1296: /* Set PAD parameters */
                   1297: 
                   1298: VOID
                   1299: setpad(s,n) CHAR *s; int n; {
                   1300:     int i;
                   1301:     CHAR *ps = s;
                   1302: 
                   1303:     for (i = 0; i < n; i++) {
                   1304:         if (*ps > MAXPADPARMS)
                   1305:          x29err[i+2] = *ps;
                   1306:         else
                   1307:          padparms[*ps] = *(ps+1);
                   1308:         ps += 2;
                   1309:     }
                   1310: }
                   1311: 
                   1312: /* Read PAD parameters */
                   1313: 
                   1314: VOID
                   1315: readpad(s,n,r) CHAR *s; int n; CHAR *r; {
                   1316:     int i;
                   1317:     CHAR *ps = s;
                   1318:     CHAR *pr = r;
                   1319: 
                   1320:     *pr++ = X29_PARAMETER_INDICATION;
                   1321:     for (i = 0; i < n; i++, ps++) {
                   1322:          if (*ps > MAXPADPARMS) {
                   1323:              x29err[i+2] = *ps++;
                   1324:          } else {
                   1325:              *pr++ = *ps;
                   1326:              *pr++ = padparms[*ps++];
                   1327:          }
                   1328:     }
                   1329: }
                   1330: 
                   1331: int
                   1332: qbitpkt(s,n) CHAR *s; int n; {
                   1333:     CHAR *ps = s;
                   1334:     int x29cmd = *ps;
                   1335:     CHAR *psa = s+1;
                   1336:     CHAR x29resp[(MAXPADPARMS*2)+1];
                   1337: 
                   1338:     switch (x29cmd) {
                   1339: 
                   1340:         case X29_SET_PARMS:
                   1341:             setpad (ps+1,n/2);
                   1342:             if ((int)strlen(x29err) > 2) {
                   1343:                 ttol (x29err,(int)strlen(x29err));
                   1344:                 x29err[2] = '\0';
                   1345:             }
                   1346:             return (-2);
                   1347:         case X29_READ_PARMS:
                   1348:             readpad (ps+1,n/2,x29resp);
                   1349:             setqbit ();
                   1350:             ttol (x29resp,n+1);
                   1351:             if ((int)strlen(x29err) > 2) {
                   1352:                 ttol (x29err,(int)strlen(x29err));
                   1353:                 x29err[2] = '\0';
                   1354:             }
                   1355:             resetqbit();
                   1356:             break;
                   1357:         case X29_SET_AND_READ_PARMS:
                   1358:             setpad (ps+1,n/2);
                   1359:             readpad (ps+1,n/2,x29resp);
                   1360:             setqbit();
                   1361:             ttol (x29resp,n+1);
                   1362:             if ((int)strlen(x29err) > 2) {
                   1363:                 ttol (x29err,(int)strlen(x29err));
                   1364:                 x29err [2] = '\0';
                   1365:             }
                   1366:             resetqbit();
                   1367:             return (-2);
                   1368:         case X29_INVITATION_TO_CLEAR:
                   1369:             (VOID) x25clear();
                   1370:             return (-1) ;
                   1371:         case X29_INDICATION_OF_BREAK:
                   1372:            break;
                   1373:     }
                   1374:     return (0);
                   1375: }
                   1376: 
                   1377: /* PAD break action processor */
                   1378: 
                   1379: VOID
                   1380: breakact() {
                   1381:     extern char x25obuf[MAXOX25];
                   1382:     extern int obufl;
                   1383:     extern int active;
                   1384:     extern unsigned char tosend;
                   1385:     static CHAR indbrk[3] = {
                   1386:        X29_INDICATION_OF_BREAK,
                   1387:        PAD_SUPPRESSION_OF_DATA,
                   1388:        1
                   1389:     };
                   1390:     CHAR intudat, cause, diag;
                   1391: 
                   1392:     if (x25stat() < 0) return(0);   /* Ignore if no virtual call established */
                   1393: 
                   1394:     if (padparms[PAD_BREAK_ACTION] != 0) /* Forward condition */
                   1395:         if (ttol(x25obuf,obufl) < 0) {
                   1396:             perror ("\r\nCan't send characters");
                   1397:             active = 0;
                   1398:         } else {
                   1399:             bzero (x25obuf,sizeof(x25obuf));
                   1400:             obufl = 0;
                   1401:             tosend = 0;
                   1402:         };
                   1403: 
                   1404:     switch (padparms[PAD_BREAK_ACTION]) {
                   1405: 
                   1406:        case 0 : break;                 /* do nothing */
                   1407:        case 1 : /* send interrupt packet with interrupt user data field = 1 */
                   1408:                intudat = 1;
                   1409:                 x25intr (intudat);
                   1410:                 break;
                   1411:        case 2 : /* send reset packet with cause and diag = 0 */
                   1412:                cause = diag = 0;
                   1413:                 x25reset (cause,diag);
                   1414:                 break;
                   1415:        case 5 : /* send interrupt packet with interrupt user data field = 0 */
                   1416:                intudat = 0;
                   1417:                 x25intr (intudat) ;
                   1418:                 setqbit ();
                   1419:                /* send indication of break without a parameter field */
                   1420:                 ttoc(X29_INDICATION_OF_BREAK);
                   1421:                 resetqbit ();
                   1422:                 break;
                   1423:        case 8 : active = 0;            /* leave data transfer */
                   1424:                 conol ("\r\n");
                   1425:                 break;
                   1426:        case 21: /* send interrupt packet with interrupt user data field = 0 */
                   1427:                intudat = 0;
                   1428:                 x25intr (intudat);
                   1429:                 setpad (indbrk+1,2);   /* set pad to discard input */
                   1430:                 setqbit ();
                   1431:                /* send indication of break with parameter field */
                   1432:                 ttol (indbrk,sizeof(indbrk));
                   1433:                 resetqbit ();
                   1434:                 break;
                   1435:      }
                   1436: }
                   1437: 
                   1438: /* X.25 support functions */
                   1439: 
                   1440: X25_CAUSE_DIAG diag;
                   1441: 
                   1442: /*
                   1443:   Convert a null-terminated string representing an X.121 address
                   1444:   to a packed BCD form.
                   1445: */
                   1446: 
                   1447: int
                   1448: pkx121(str,bcd) char *str; CHAR *bcd; {
                   1449:     int i, j;
                   1450:     u_char c;
                   1451: 
                   1452:     i = j = 0;
                   1453:     while (str[i]) {
                   1454:         if ( i >= 15 || str [i] < '0' || str [i] > '9' )
                   1455:          return (-1);
                   1456:         c = str [i] - '0';
                   1457:         if ( i & 1 )
                   1458:          bcd [j++] |= c;
                   1459:         else
                   1460:          bcd [j] = c << 4;
                   1461:         i++;
                   1462:     }
                   1463:     return (i);
                   1464: }
                   1465: 
                   1466: /* Reads and prints X.25 diagnostic */
                   1467: 
                   1468: int
                   1469: x25diag () {
                   1470:     int i;
                   1471: 
                   1472:     bzero ((char *)&diag,sizeof(diag));
                   1473:     if (ioctl(ttyfd,X25_RD_CAUSE_DIAG,&diag)) {
                   1474:         perror ("Reading X.25 diagnostic");
                   1475:         return(-1);
                   1476:     }
                   1477:     if (diag.datalen > 0) {
                   1478:         printf ("X.25 Diagnostic :");
                   1479:         for (i = 0; i < diag.datalen; i++) printf (" %02x",diag.data[i]);
                   1480:         printf ("\r\n");
                   1481:     }
                   1482:     return(0);
                   1483: }
                   1484: 
                   1485: /* X.25 Out-of-Band Signal Handler */
                   1486: 
                   1487: VOID
                   1488: x25oobh() {
                   1489:     int oobtype;
                   1490:     u_char oobdata;
                   1491: 
                   1492:     (VOID) signal(SIGURG,x25oobh);
                   1493:     do {
                   1494:         if (ioctl(ttyfd,X25_OOB_TYPE,&oobtype)) {
                   1495:             perror ("Getting signal type");
                   1496:             return;
                   1497:         }
                   1498:         switch (oobtype) {
                   1499:          case INT_DATA:
                   1500:            if (recv(ttyfd,oobdata,1,MSG_OOB) < 0) {
                   1501:                perror ("Receiving X.25 interrupt data");
                   1502:                return;
                   1503:            }
                   1504:            printf ("\r\nInterrupt received, data = %d\r\n", oobdata);
                   1505:            break;
                   1506:          case VC_RESET:
                   1507:            printf ("\r\nVirtual circuit reset\r\n");
                   1508:            x25diag ();
                   1509:            break;
                   1510:          case N_RESETS:
                   1511:            printf ("\r\nReset timeout\r\n");
                   1512:            break;
                   1513:          case N_CLEARS:
                   1514:            printf ("\r\nClear timeout\r\n");
                   1515:            break;
                   1516:          case MSG_TOO_LONG:
                   1517:            printf ("\r\nMessage discarded, too long\r\n");
                   1518:            break;
                   1519:          default:
                   1520:            if (oobtype) printf("\r\nUnknown oob type %d\r\n",oobtype);
                   1521:            break;
                   1522:        }
                   1523:     } while (oobtype);
                   1524: }
                   1525: 
                   1526: /* Send a X.25 interrupt packet */
                   1527: 
                   1528: int
                   1529: #ifdef CK_ANSIC
                   1530: x25intr(char intr)
                   1531: #else
                   1532: x25intr(intr) char intr;
                   1533: #endif /* CK_ANSIC */
                   1534: /* x25intr */ {
                   1535:     if (send(ttyfd,&intr,1,MSG_OOB) < 0) return(-1);
                   1536:     debug(F100,"X.25 intr","",0);
                   1537:     return(0);
                   1538: }
                   1539: 
                   1540: /* Reset X.25 virtual circuit */
                   1541: int
                   1542: #ifdef CK_ANSIC
                   1543: x25reset(char cause, char diagn)
                   1544: #else
                   1545: x25reset(cause, diagn) char cause; char diagn;
                   1546: #endif /* CK_ANSIC */
                   1547: /* x25reset */ {
                   1548:     bzero ((char *)&diag,sizeof(diag));
                   1549:     diag.flags   = 0;
                   1550:     diag.datalen = 2;
                   1551:     diag.data[0] = cause;
                   1552:     diag.data[1] = diagn;
                   1553:     if (ioctl(ttyfd,X25_WR_CAUSE_DIAG,&diag) < 0)
                   1554:       return(-1);
                   1555:     debug(F100,"X.25 reset","",0);
                   1556:     return(0);
                   1557: }
                   1558: 
                   1559: /* Clear X.25 virtual circuit */
                   1560: int
                   1561: x25clear() {
                   1562:     int i;
                   1563:     debug(F100,"X.25 clear","",0);
                   1564:     bzero ((char *)&diag,sizeof(diag));
                   1565:     diag.flags = (1 << DIAG_TYPE);
                   1566:     diag.datalen = 2;
                   1567:     diag.data[0] = 0;
                   1568:     diag.data[1] = 0;
                   1569:     ioctl (ttyfd,X25_WR_CAUSE_DIAG,&diag); /* Send Clear Request */
                   1570:     return(ttclos(0));                 /* Close socket */
                   1571: }
                   1572: 
                   1573: /* X.25 status */
                   1574: int
                   1575: x25stat() {
                   1576:     if (ttyfd < 0) return (-1);
                   1577:     return(0);
                   1578: }
                   1579: 
                   1580: /* Set Q_BIT on */
                   1581: VOID
                   1582: setqbit() {
                   1583:     static int qbiton = 1 << Q_BIT;
                   1584:     ioctl (ttyfd,X25_SEND_TYPE,&qbiton);
                   1585: }
                   1586: 
                   1587: /* Set Q_BIT off */
                   1588: VOID
                   1589: resetqbit() {
                   1590:     static int qbitoff = 0;
                   1591:     ioctl (ttyfd,X25_SEND_TYPE,&qbitoff);
                   1592: }
                   1593: 
                   1594: /* Read n characters from X.25 circuit into buf */
                   1595: 
                   1596: int
                   1597: x25xin(n,buf) int n; CHAR *buf; {
                   1598:     register int x, c;
                   1599:     int qpkt;
                   1600: 
                   1601:     do {
                   1602:        x = read(ttyfd,buf,n);
                   1603:        if (buf[0] & (1 << Q_BIT)) { /* If Q_BIT packet, process it */
                   1604:            /* If return -1 : invitation to clear; -2 : PAD changes */
                   1605:            if ((c=qbitpkt(buf+1,x-2)) < 0) return(c);
                   1606:            qpkt = 1;
                   1607:        } else qpkt = 0;
                   1608:     } while (qpkt);
                   1609:     if (x > 0) buf[x] = '\0';
                   1610:     if (x < 1) x = -1;
                   1611:     debug(F101,"x25xin x","",x);
                   1612: 
                   1613:     return(x);
                   1614: }
                   1615: 
                   1616: #ifdef COMMENT /* NO LONGER NEEDED! */
                   1617: /* X.25 read a line */
                   1618: 
                   1619: int
                   1620: #ifdef PARSENSE
                   1621: #ifdef CK_ANSIC
                   1622: x25inl(CHAR *dest, int max,int timo, CHAR eol, CHAR start)
                   1623: #else
                   1624: x25inl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start;
                   1625: #endif /* CK_ANSIC */
                   1626: #else /* not PARSENSE */
                   1627: #ifdef CK_ANSIC
                   1628: x25inl(CHAR *dest, int max,int timo, CHAR eol)
                   1629: #else
                   1630: x25inl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
                   1631: #endif /* __SDTC__ */
                   1632: #endif /* PARSENSE */
                   1633: /* x25inl */ {
                   1634:     CHAR *pdest;
                   1635:     int pktype, goteol, rest, n;
                   1636:     int i, flag = 0;
                   1637:     extern int ttprty, ttpflg;
                   1638:     int ttpmsk;
                   1639: 
                   1640:     ttpmsk = (ttprty) ? 0177 : 0377;   /* Set parity stripping mask */
                   1641: 
                   1642:     debug(F101,"x25inl max","",max);
                   1643:     debug(F101,"x25inl eol","",eol);
                   1644:     pdest  = dest;
                   1645:     rest   = max;
                   1646:     goteol = 0;
                   1647:     do {
                   1648:        n = read(ttyfd,pdest,rest);
                   1649:        n--;
                   1650:        pktype = *pdest & 0x7f;
                   1651:        switch (pktype) {
                   1652:          case 1 << Q_BIT:
                   1653:            if (qbitpkt(pdest+1,--n) < 0) return(-2);
                   1654:            break;
                   1655:          default:
                   1656:            if (flag == 0) { /* if not in packet, search start */
                   1657:                for (i = 1; (i < n) &&
                   1658:                     !(flag = ((dest[i] & 0x7f) == start));
                   1659:                     i++);
                   1660:                if (flag == 0) { /* not found, discard junk */
                   1661:                    debug(F101,"x25inl skipping","",n);
                   1662:                    continue;
                   1663:                } else {                /* found, discard junk before start */
                   1664:                    int k;
                   1665:                    n = n - i + 1;
                   1666:                    for (k = 1; k <= n; k++, i++) dest[k] = dest[i];
                   1667:                }
                   1668:            }
                   1669:            for (i = 0; (i < n) && /* search for eol */
                   1670:                 !(goteol=(((*pdest = *(pdest+1)&ttpmsk)&0x7f)== eol));
                   1671:                 i++,pdest++);
                   1672:            *pdest = '\0';
                   1673:            rest -= n;
                   1674:        }
                   1675:     } while ( (rest > 0) && (!goteol) );
                   1676: 
                   1677:     if (goteol) {
                   1678:        n = max - rest;
                   1679:        debug (F111,"x25inl X.25 got",(char *) dest,n);
                   1680:        if (timo) ttimoff();
                   1681:        if (ttpflg++ == 0 && ttprty == 0) {
                   1682:            if ((ttprty = parchk(dest,start,n)) > 0) {
                   1683:                int j;
                   1684:                debug(F101,"x25inl senses parity","",ttprty);
                   1685:                debug(F110,"x25inl packet before",(char *)dest,0);
                   1686:                ttpmsk = 0x7f;
                   1687:                for (j = 0; j < n; j++)
                   1688:                  dest[j] &= 0x7f; /* Strip parity from packet */
                   1689:                debug(F110,"x25inl packet after ",dest,0);
                   1690:            } else {
                   1691:                debug(F101,"parchk","",ttprty);
                   1692:                if (ttprty < 0) { ttprty = 0; n = -1; }
                   1693:            }
                   1694:        }
                   1695:        ttimoff();
                   1696:        return(n);
                   1697:     }
                   1698:     ttimoff();
                   1699:     return(-1);
                   1700: }
                   1701: #endif /* COMMENT */
                   1702: #endif /* SUNX25 */
                   1703: 
                   1704: #endif /* NETCONN */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.