Annotation of coherent/g/usr/bin/ckermit/ckcnet.c, revision 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.