Annotation of 43BSD/contrib/xns/examples/gap/gaptelnetd.c, revision 1.1

1.1     ! root        1: #ifndef lint
        !             2: static char RCSid[] = "$Header: gaptelnetd.c,v 2.0 85/11/21 07:23:06 jqj Exp $";
        !             3: #endif
        !             4: /*
        !             5:  * server for GAP-style (TransportObject=server,teletype) telnet connections
        !             6:  * Note that we support only GAP version 3
        !             7:  */
        !             8: 
        !             9: /* $Log:       gaptelnetd.c,v $
        !            10:  * Revision 2.0  85/11/21  07:23:06  jqj
        !            11:  * 4.3BSD standard release
        !            12:  * 
        !            13:  * Revision 1.3  85/11/21  06:53:22  jqj
        !            14:  * symbolic values for connection type
        !            15:  * 
        !            16:  * Revision 1.2  85/11/08  17:17:13  bill
        !            17:  * version on bullwinkle
        !            18:  * 
        !            19:  * Revision 1.3  85/08/05  09:58:00  jqj
        !            20:  * fixed for Interlisp -- data from Interlisp appears with dt==0 (wrong!)
        !            21:  * also, Interlisp trys to connect to a tty rather than a ttyHost.
        !            22:  * increased inactivity timeout to 4 hrs
        !            23:  *
        !            24:  * Revision 1.2  85/05/23  06:22:18  jqj
        !            25:  * *** empty log message ***
        !            26:  * 
        !            27:  * Revision 1.1  85/05/22  09:46:52  jqj
        !            28:  * Initial revision
        !            29:  */
        !            30: #include <stdio.h>
        !            31: #include <signal.h>
        !            32: #include <sgtty.h>
        !            33: #include <sys/types.h>
        !            34: #include <sys/time.h>
        !            35: #include <sys/uio.h>
        !            36: #include <sys/socket.h>
        !            37: #include <netns/ns.h>
        !            38: #include <netns/idp.h>
        !            39: #include <netns/sp.h>
        !            40: #include <sys/wait.h>
        !            41: #include <xnscourier/realcourierconnection.h>
        !            42: #include "GAP3.h"
        !            43: #include "gapcontrols.h"
        !            44: #include <xnscourier/except.h>
        !            45: #include <errno.h>
        !            46: 
        !            47: #define        BELL    '\07'
        !            48: #define BANNER "\r\n\r\n4.3 BSD UNIX (%s)\r\n\r\r\n\r"
        !            49: 
        !            50: int pty, net;
        !            51: extern CourierConnection *_serverConnection;
        !            52: char buf[sizeof(struct sphdr)+SPPMAXDATA];
        !            53: struct sphdr our_sphdr;
        !            54: struct iovec our_iovec[2] = {{((caddr_t)&our_sphdr), sizeof(our_sphdr)}};
        !            55: /*
        !            56:  * I/O data buffers, pointers, and counters.
        !            57:  */
        !            58: char   ptyibuf[512], *ptyip = ptyibuf;
        !            59: char   ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;
        !            60: char   *netip = buf;
        !            61: char   netobuf[512], *nfrontp = netobuf, *nbackp = netobuf;
        !            62: int    pcc, ncc;
        !            63: char   line[12];
        !            64: extern char **environ;
        !            65: extern int errno;
        !            66: 
        !            67: char *envinit[3];
        !            68: char wsenv[50];
        !            69: 
        !            70: /*
        !            71:  * session parameters
        !            72:  */
        !            73: Cardinal frametimeout;         /* 0 or time in seconds to wait */
        !            74: 
        !            75: 
        !            76: /*
        !            77:  * This modified version of the server is necessary since GAP specifies
        !            78:  * that the telnet data-transfer session occurs after the RPC to create
        !            79:  * it has returned!
        !            80:  */
        !            81: Server(skipcount,skippedwords)
        !            82:        int skipcount;
        !            83:        Unspecified skippedwords[];
        !            84: {
        !            85:        Cardinal _procedure;
        !            86:        register Unspecified *_buf;
        !            87:        LongCardinal programnum;
        !            88:        Cardinal versionnum;
        !            89:        Cardinal _n;
        !            90: 
        !            91: #ifdef DEBUG
        !            92:        BUGOUT("Server: %d %d",skipcount,skippedwords);
        !            93: #endif
        !            94:        for (;;) {
        !            95:                _buf = ReceiveCallMessage(&_procedure, skipcount, skippedwords);
        !            96:                DURING switch (_procedure) {
        !            97:                case 3:
        !            98:                        server_GAP3_Delete(_buf);
        !            99:                        break;
        !           100:                case 2:
        !           101:                        server_GAP3_Create(_buf);
        !           102:                        net = _serverConnection->fd;
        !           103:                        gaptelnet(); /* returns on connection close */
        !           104:                        break;
        !           105:                case 0:
        !           106:                        server_GAP3_Reset(_buf);
        !           107:                        break;
        !           108:                default:
        !           109:                        NoSuchProcedureValue("GAP", _procedure);
        !           110:                        break;
        !           111:                } HANDLER {
        !           112:                    Deallocate(_buf);
        !           113:                    switch (Exception.Code) {
        !           114:                    case GAP3_serviceNotFound:
        !           115:                    case GAP3_userNotAuthorized:
        !           116:                    case GAP3_userNotAuthenticated:
        !           117:                    case GAP3_serviceTooBusy:
        !           118:                    case GAP3_terminalAddressInvalid:
        !           119:                    case GAP3_terminalAddressInUse:
        !           120:                    case GAP3_controllerDoesNotExist:
        !           121:                    case GAP3_controllerAlreadyExists:
        !           122:                    case GAP3_gapCommunicationError:
        !           123:                    case GAP3_gapNotExported:
        !           124:                    case GAP3_bugInGAPCode:
        !           125:                    case GAP3_tooManyGateStreams:
        !           126:                    case GAP3_inconsistentParams:
        !           127:                    case GAP3_transmissionMediumUnavailable:
        !           128:                    case GAP3_dialingHardwareProblem:
        !           129:                    case GAP3_noDialingHardware:
        !           130:                    case GAP3_badAddressFormat:
        !           131:                    case GAP3_mediumConnectFailed:
        !           132:                    case GAP3_illegalTransport:
        !           133:                    case GAP3_noCommunicationHardware:
        !           134:                    case GAP3_unimplemented:
        !           135:                        _buf = Allocate(0);
        !           136:                        SendAbortMessage(Exception.Code-ERROR_OFFSET, 0, _buf);
        !           137:                        break;
        !           138:                    default:
        !           139:                        _buf = Allocate(0);
        !           140:                        SendRejectMessage(unspecifiedError, 0, _buf);
        !           141:                        break;
        !           142:                    }
        !           143:                } END_HANDLER;
        !           144:                Deallocate(_buf);
        !           145:                for (;;) {
        !           146:                        skipcount = LookAheadCallMsg(&programnum, &versionnum,
        !           147:                                        skippedwords);
        !           148:                        if (skipcount < 0) return(0);   /* timed out */
        !           149:                        if (programnum != 3 || versionnum != 3)
        !           150:                                ExecCourierProgram(programnum, versionnum,
        !           151:                                                skipcount, skippedwords);
        !           152:                }  /* loop if can't exec that program */
        !           153:        }
        !           154: }
        !           155: 
        !           156: void
        !           157: GAP3_Delete(session)
        !           158:        GAP3_SessionHandle session; 
        !           159: {
        !           160: }
        !           161: 
        !           162: void
        !           163: GAP3_Reset()
        !           164: {
        !           165: }
        !           166: 
        !           167: GAP3_CreateResults
        !           168: GAP3_Create(conn, BDTproc, sessionparams, transports,
        !           169:            createTimeout, credentials, verifier)
        !           170:        CourierConnection *conn;
        !           171:        int BDTproc;
        !           172:        GAP3_SessionParameterObject sessionparams;
        !           173:        struct {Cardinal length;
        !           174:                GAP3_TransportObject *sequence;
        !           175:        } transports;
        !           176:        GAP3_WaitTime createTimeout;
        !           177:        Authentication1_Credentials credentials;
        !           178:        Authentication1_Verifier verifier;
        !           179: {
        !           180:        GAP3_CreateResults result;
        !           181:        char *c1, *c2, *host;
        !           182:        int t, pid;
        !           183:        struct sgttyb b;
        !           184:        char *xntoa(), *wsname();
        !           185:        struct sockaddr_ns who;
        !           186:        int whosize = sizeof(who);
        !           187:        LongCardinal servicetype;
        !           188:        GAP3_CommParamObject *cp;
        !           189:        GAP3_Duplexity duplexity;       /* fullDuplex, halfDuplex */
        !           190: 
        !           191: #ifdef DEBUG
        !           192:        BUGOUT("CREATE");
        !           193: #endif
        !           194:        switch (sessionparams.designator) {
        !           195:        case oldTty:
        !           196:        case oldTtyHost:
        !           197:                frametimeout = sessionparams.oldTtyHost_case.frameTimeout/1000;
        !           198:                /* could set other parameters here */
        !           199:                break;
        !           200:        case tty:
        !           201:        case ttyHost:
        !           202:                frametimeout = sessionparams.ttyHost_case.frameTimeout/1000;
        !           203:                /* could set other parameters here */
        !           204:                break;
        !           205:        default:
        !           206:                raise(GAP3_unimplemented, 0);
        !           207:                /*NOTREACHED*/
        !           208:        }
        !           209:        if (transports.length != 2) {
        !           210:                raise(GAP3_illegalTransport);
        !           211:                /*NOTREACHED*/
        !           212:        }
        !           213:        switch (transports.sequence[0].designator) {
        !           214:        case service:
        !           215:                servicetype = transports.sequence[0].service_case.id;
        !           216:                switch (servicetype) {
        !           217:                case TTYService_any:            /* 0 */
        !           218:                        servicetype = TTYService_sa;
        !           219:                case TTYService_sa:             /* 1 */
        !           220:                case TTYService_exec:           /* 2 */
        !           221:                case TTYService_its:            /* 3 */
        !           222:                        break;
        !           223:                default:
        !           224:                        raise(GAP3_serviceNotFound, 0);
        !           225:                        /*NOTREACHED*/
        !           226:                }
        !           227:                duplexity = fullduplex;/* services are allways fulldup */
        !           228:                break;
        !           229:        case rs232c:    /* maybe some day */
        !           230:                cp = &transports.sequence[0].rs232c_case.commParams;
        !           231:                if (cp->accessDetail.designator == directConn) {
        !           232:                        duplexity = cp->accessDetail.directConn_case.duplex;
        !           233:                        servicetype = TTYService_sa; /* fake it */
        !           234:                        break;
        !           235:                }
        !           236:                raise(GAP3_noCommunicationHardware, 0);
        !           237:                /*NOTREACHED*/
        !           238:        default:
        !           239:                raise(GAP3_illegalTransport, 0);
        !           240:                /*NOTREACHED*/
        !           241:        }
        !           242:        if (transports.sequence[1].designator != teletype)
        !           243:          raise(GAP3_illegalTransport, 0);
        !           244:        /* ignore createTimeout */
        !           245:        /* ignore credentials and verifier */
        !           246:        
        !           247:        for (c1 = "pq"; *c1 != 0; c1++)
        !           248:          for (c2 = "0123456789abcdef"; *c2 != 0; c2++) {
        !           249:                  sprintf(line, "/dev/pty%c%c", *c1, *c2);
        !           250:                  pty = open(line, 2);
        !           251:                  if (pty < 0) continue;
        !           252:                  line[strlen("/dev/")] = 't';
        !           253:                  t = open(line, 2);
        !           254:                  if (t > 0) goto gotpty;
        !           255:                  close(pty);
        !           256:          }
        !           257:        raise(GAP3_serviceTooBusy, 0);
        !           258:        /*NOTREACHED*/
        !           259:  gotpty:
        !           260:        getpeername(_serverConnection->fd, &who, &whosize);
        !           261:        host = wsname(who.sns_addr);
        !           262: #ifdef DEBUG
        !           263:        BUGOUT("gotpty <%s> %d <%s>",line, pty, host);
        !           264: #endif
        !           265:        ioctl(t, TIOCGETP, &b);
        !           266:        b.sg_flags = CRMOD|XTABS|ANYP;
        !           267:        ioctl(t, TIOCSETP, &b);
        !           268:        ioctl(pty, TIOCGETP, &b);
        !           269:        if (duplexity == fullduplex)
        !           270:          b.sg_flags |= ECHO;
        !           271:        else
        !           272:          b.sg_flags &= ~ECHO;
        !           273:        ioctl(pty, TIOCSETP, &b);
        !           274:        /* we do the fork now so we can return failures as REPORTS */
        !           275:        pid = fork();
        !           276:        if (pid < 0) {
        !           277:                close(pty); close(t);
        !           278:                raise(GAP3_serviceTooBusy, 0);
        !           279:                /*NOTREACHED*/
        !           280:        }
        !           281:        else if (pid == 0) {    /* in the execed fork */
        !           282:                sleep(1);       /* let parent get ready for us */
        !           283:                close(_serverConnection->fd); /* close net */
        !           284:                close(pty);
        !           285:                dup2(t, 0);
        !           286:                dup2(t, 1);
        !           287:                dup2(t, 2);
        !           288:                if (t > 2) close(t);
        !           289:                envinit[0] = "TERM=network";
        !           290:                envinit[1] = sprintf(wsenv, "WORKSTATION=%s",
        !           291:                                     xntoa(who.sns_addr));
        !           292:                envinit[2] = (char*) 0;
        !           293: #ifdef DEBUG
        !           294:                BUGOUT("about to exec /bin/login");
        !           295: #endif
        !           296:                execl("/bin/login","login", "-h", host, 0);
        !           297: #ifdef DEBUG
        !           298:                BUGOUT("exec of /bin/login failed");
        !           299: #endif
        !           300:                perror("/bin/login");
        !           301:                exit(1);
        !           302:                /*NOTREACHED*/
        !           303:        }
        !           304:        close(t);
        !           305: #ifdef DEBUG
        !           306:        BUGOUT("fork successful");
        !           307: #endif
        !           308:        result.session[0] = pid;
        !           309:        return(result);
        !           310: }
        !           311: 
        !           312: jmp_buf childdiedbuf;
        !           313: 
        !           314: /*
        !           315:  * Main loop.  Select from pty and network, and
        !           316:  * hand data to telnet receiver finite state machine.
        !           317:  * Returns 0 on orderly shutdown, 1 on abnormal shutdown.
        !           318:  */
        !           319: gaptelnet()
        !           320: {
        !           321:        int on = 1;
        !           322:        char hostname[32];
        !           323:        int childdied();
        !           324:        int ibits = 0, obits = 0;
        !           325:        register int c;
        !           326:        struct sphdr *si = (struct sphdr *)buf;
        !           327:        static struct timeval timeout = {600,0};
        !           328:        int keepalives = 0;
        !           329:        int i;
        !           330: 
        !           331: #ifdef DEBUG
        !           332:        BUGOUT("gaptelnet net=%d,pty=%d",net,pty);
        !           333: #endif
        !           334:        if (setjmp(childdiedbuf) != 0)
        !           335:          return(0);            /* child died */
        !           336:        signal(SIGCHLD, childdied);
        !           337:        signal(SIGTSTP, SIG_IGN);
        !           338:        ioctl(net, FIONBIO, &on);
        !           339:        ioctl(pty, FIONBIO, &on);
        !           340: 
        !           341: 
        !           342:        /*
        !           343:         * Show banner that getty never gave.
        !           344:         */
        !           345:        gethostname(hostname, sizeof (hostname));
        !           346:        sprintf(nfrontp, BANNER, hostname);
        !           347:        nfrontp += strlen(nfrontp);
        !           348:        /*
        !           349:         * Send status message indicating we're ready to go
        !           350:         */
        !           351:        changeSPPopts(net, GAPCTLnone, 1);
        !           352:        sendoobdata(GAPCTLmediumUp);
        !           353:        for (;;) {
        !           354: #ifdef DEBUG
        !           355:                BUGOUT("looping in gaptelnet");
        !           356: #endif
        !           357:                ibits = obits = 0;
        !           358:                /*
        !           359:                 * Never look for input if there's still
        !           360:                 * stuff in the corresponding output buffer
        !           361:                 */
        !           362:                if (nfrontp - nbackp || pcc > 0)
        !           363:                        obits |= (1 << net);
        !           364:                else
        !           365:                        ibits |= (1 << pty);
        !           366:                if (pfrontp - pbackp || ncc > 0)
        !           367:                        obits |= (1 << pty);
        !           368:                else
        !           369:                        ibits |= (1 << net);
        !           370:                if (ncc < 0 && pcc < 0)
        !           371:                        break;
        !           372:                timeout.tv_sec = 14400;         /* 4 hrs. */
        !           373:                timeout.tv_usec = 0;
        !           374:                select(16, &ibits, &obits, 0, &timeout);
        !           375:                if (ibits == 0 && obits == 0) {
        !           376:                        /* timeout means no activity for a long time */
        !           377: #ifdef DEBUG
        !           378:                        BUGOUT("timeout from select");
        !           379: #endif
        !           380:                        if (keepalives++ < 2) {
        !           381:                          /* first time through send warning */
        !           382:                                if (nfrontp == nbackp && pcc == 0) {
        !           383:                                        /* but only if not blocked on output */
        !           384: #define WARNING "\r\nYou've been idle much too long.  Respond or log off.\r\n"
        !           385:                                        strcpy(nfrontp, WARNING);
        !           386:                                        nfrontp += sizeof(WARNING);
        !           387:                                }
        !           388:                                sleep(5);
        !           389:                                continue;
        !           390:                        }
        !           391: #ifdef DEBUG
        !           392:                        BUGOUT("keepalive expired -- calling cleanup");
        !           393: #endif
        !           394:                        /* keepalive count has expired */
        !           395:                        cleanup();
        !           396:                        return(1);
        !           397:                }
        !           398: 
        !           399:                /*
        !           400:                 * Something to read from the network...
        !           401:                 */
        !           402:                if (ibits & (1 << net)) {
        !           403:                        ncc = read(net, buf, sizeof(buf));
        !           404: #ifdef DEBUG
        !           405:                        BUGOUT("read %d from net, cc=0%o,dt=0%o",
        !           406:                                ncc-sizeof(struct sphdr), si->sp_cc, si->sp_dt);
        !           407: #endif
        !           408:                        if (ncc < 0 && errno == EWOULDBLOCK)
        !           409:                                ncc = 0;
        !           410:                        else if (ncc < sizeof(struct sphdr)) {
        !           411: #ifdef DEBUG
        !           412:                                BUGOUT("short read, %d.  calling cleanup",ncc);
        !           413: #endif
        !           414:                                cleanup(); /* will probably fail or block */
        !           415:                                return(1);
        !           416:                        }
        !           417:                        else if (si->sp_cc & SP_OB) {
        !           418: #ifdef DEBUG
        !           419:                                BUGOUT("Got OOB control 0%o",
        !           420:                                        (u_char) buf[sizeof(struct sphdr)]);
        !           421: #endif
        !           422:                                /* a status or OOB control */
        !           423:                                switch ((u_char) buf[sizeof(struct sphdr)]) {
        !           424:                                case GAPCTLinterrupt:
        !           425:                                        /* shove interrupt char in buffer */
        !           426:                                        interrupt();
        !           427:                                        break; /* from switch */
        !           428:                                case GAPCTLareYouThere:
        !           429:                                        sendoobdata(GAPCTLiAmHere);
        !           430:                                        break; /* from switch */
        !           431:                                default:
        !           432:                                        /* Ignore other controls instead of:
        !           433:                                         * sendoobdata(
        !           434:                                         *     GAPCTLunexpectedRemoteBehavior);
        !           435:                                         */
        !           436:                                        break; /* from switch */
        !           437:                                }
        !           438:                                ncc = 0; /* no chars here */
        !           439:                        }
        !           440:                        else if (si->sp_dt==GAPCTLnone ||
        !           441:                                 si->sp_dt==0) {
        !           442:                                /* the normal case */
        !           443:                                /* N.B. the standard says dt should be 0300
        !           444:                                 * i.e. GAPCTLnone, but Interlisp CHAT
        !           445:                                 * generates 0, so we accept that too.
        !           446:                                 */
        !           447:                                ncc -= sizeof(struct sphdr);
        !           448: #ifdef DEBUG
        !           449:                                BUGOUT("Now ncc == %d",ncc);
        !           450: #endif
        !           451:                                netip = buf + sizeof(struct sphdr);
        !           452:                                keepalives = 0;
        !           453:                        }
        !           454:                        else if(si->sp_dt==GAPCTLcleanup) {
        !           455: #ifdef DEBUG
        !           456:                                BUGOUT("got CLEANUP packet.  Done");
        !           457: #endif
        !           458:                                cleanup(); /* normal termination */
        !           459:                                return(0);
        !           460:                        }
        !           461:                        else if (si->sp_dt==SPPSST_END) {
        !           462:                                /* got premature termination */
        !           463:                                quitquit(net, pty);
        !           464:                                return(1);
        !           465:                        }
        !           466:                        else {
        !           467:                                /* some other inband ctl */
        !           468: #ifdef DEBUG
        !           469:                                BUGOUT("ignoring IB packet, data = 0%o...",
        !           470:                                        (u_char) buf[sizeof(struct sphdr)]);
        !           471: #endif
        !           472:                        }
        !           473:                }
        !           474: 
        !           475:                /*
        !           476:                 * Something to read from the pty...
        !           477:                 */
        !           478:                if (ibits & (1 << pty)) {
        !           479:                        if (frametimeout > 0) sleep(frametimeout);
        !           480:                        pcc = read(pty, ptyibuf, sizeof(ptyibuf));
        !           481: #ifdef DEBUG
        !           482:                        BUGOUT("read from pty %d",pcc);
        !           483: #endif
        !           484:                        if (pcc < 0 && errno == EWOULDBLOCK)
        !           485:                                pcc = 0;
        !           486:                        else if (pcc <= 0) {
        !           487: #ifdef DEBUG
        !           488:                                BUGOUT("short read from pty. Calling cleanup");
        !           489: #endif
        !           490:                                cleanup();
        !           491:                                return(1); /* ?? abnormal termination */
        !           492:                        }
        !           493:                        ptyip = ptyibuf;
        !           494:                }
        !           495: 
        !           496:                while (pcc > 0) {
        !           497:                        if ((&netobuf[sizeof(netobuf)] - nfrontp) < 2)
        !           498:                                break;
        !           499:                        *nfrontp++ = *ptyip++ & 0377; pcc--;
        !           500:                }
        !           501:                if ((obits & (1 << net)) && (nfrontp - nbackp) > 0)
        !           502:                        netflush();
        !           503:                while (ncc > 0) {
        !           504:                        if ((&ptyobuf[sizeof(ptyobuf)] - pfrontp) < 2) break;
        !           505:                        *pfrontp++ = *netip++ & 0377;
        !           506:                        ncc--;
        !           507:                }
        !           508:                if ((obits & (1 << pty)) && (pfrontp - pbackp) > 0)
        !           509:                        ptyflush();
        !           510:        }
        !           511:        /* we should never get to here */
        !           512: #ifdef DEBUG
        !           513:        BUGOUT("broke out of for(;;) somehow.  calling cleanup");
        !           514: #endif
        !           515:        cleanup();
        !           516:        return(0);
        !           517: }
        !           518: 
        !           519: /*
        !           520:  * Send out of band data to other end of network
        !           521:  */
        !           522: sendoobdata(value)
        !           523:        u_char value;
        !           524: {
        !           525:        struct {
        !           526:                struct sphdr hdr;
        !           527:                char val;
        !           528:        } oob;
        !           529:        oob.hdr = our_sphdr;
        !           530:        oob.val = value;
        !           531: #ifdef DEBUG
        !           532:        BUGOUT("sendoobdata 0%o",value);
        !           533: #endif
        !           534:        send(net, &oob, sizeof(oob), MSG_OOB);
        !           535: }
        !           536: 
        !           537: /*
        !           538:  * Send interrupt to process on other side of pty.
        !           539:  * If it is in raw mode, just write NULL;
        !           540:  * otherwise, write intr char.
        !           541:  */
        !           542: interrupt()
        !           543: {
        !           544:        struct sgttyb b;
        !           545:        struct tchars tchars;
        !           546: 
        !           547:        ptyflush();     /* half-hearted */
        !           548:        ioctl(pty, TIOCGETP, &b);
        !           549:        if (b.sg_flags & RAW) {
        !           550:                *pfrontp++ = '\0';
        !           551:                return;
        !           552:        }
        !           553:        *pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ?
        !           554:                '\177' : tchars.t_intrc;
        !           555: }
        !           556: 
        !           557: ptyflush()
        !           558: {
        !           559:        register int n;
        !           560: 
        !           561:        if ((n = pfrontp - pbackp) > 0)
        !           562:                n = write(pty, pbackp, n);
        !           563: #ifdef DEBUG
        !           564:        BUGOUT("ptyflush wrote %d",n);
        !           565: #endif
        !           566:        if (n < 0)
        !           567:                return;
        !           568:        pbackp += n;
        !           569:        if (pbackp >= pfrontp)  /* actually, > is an error */
        !           570:                pbackp = pfrontp = ptyobuf;
        !           571: }
        !           572: 
        !           573: netflush()
        !           574: {
        !           575:        register int n;
        !           576: 
        !           577:        if ((n = nfrontp - nbackp) > 0) {
        !           578:                our_iovec[1].iov_len = ((n > SPPMAXDATA) ? SPPMAXDATA : n);
        !           579:                our_iovec[1].iov_base = nbackp;
        !           580:                n = writev(net, our_iovec, 2) - sizeof(struct sphdr);
        !           581:        }
        !           582: #ifdef DEBUG
        !           583:        BUGOUT("netflush wrote %d",n);
        !           584:        if (our_iovec[0].iov_base != (char*)&our_sphdr)
        !           585:                BUGOUT("Oops:  our_iovec clobbered");
        !           586:        BUGOUT("header: %d %d, %d %d %d %d %d %d",
        !           587:                our_sphdr.sp_cc, our_sphdr.sp_dt, 
        !           588:                our_sphdr.sp_sid, our_sphdr.sp_did, our_sphdr.sp_seq, 
        !           589:                our_sphdr.sp_ack, our_sphdr.sp_alo);
        !           590: #endif
        !           591:        if (n < 0) {
        !           592:                if (errno == EWOULDBLOCK)
        !           593:                        return;
        !           594:                /* should blow this guy away... */
        !           595:                return;
        !           596:        }
        !           597:        nbackp += n;
        !           598:        if (nbackp >= nfrontp)  /* actually , > is an error */
        !           599:                nbackp = nfrontp = netobuf;
        !           600: }
        !           601: 
        !           602: /*
        !           603:  * handle receipt of an SPPSST_END packet
        !           604:  * This is currently an error, since client didn't send "cleanup" first
        !           605:  */
        !           606: quitquit()
        !           607: {
        !           608: #ifdef DEBUG
        !           609:        BUGOUT("quitquit");
        !           610: #endif
        !           611:        changeSPPopts(net, SPPSST_ENDREPLY, 1);
        !           612:        write(net, &our_sphdr, sizeof(our_sphdr));
        !           613:        sleep(3);
        !           614: 
        !           615:        rmut();
        !           616:        vhangup();      /* XXX */
        !           617:        shutdown(net, 1);
        !           618:        close(net);
        !           619: }
        !           620: 
        !           621: /*
        !           622:  * shut down the data connection for one reason or another
        !           623:  */
        !           624: cleanup()
        !           625: {
        !           626:        int fdmask;
        !           627:        struct timeval timeout;
        !           628:        struct sphdr *si = (struct sphdr *)buf;
        !           629:        int off = 0;
        !           630: 
        !           631:        signal(SIGCHLD, SIG_IGN);
        !           632:        sendoobdata(GAPCTLcleanup);
        !           633:        changeSPPopts(net, SPPSST_END, 1);
        !           634:        if (write(net, &our_sphdr, sizeof(our_sphdr)) < 0) {
        !           635:                fdmask = 1<<net;
        !           636:                timeout.tv_sec = 10;
        !           637:                while (select(net+1,&fdmask,(int*)0, (int*)0, &timeout) > 0 &&
        !           638:                       read(net,buf,sizeof(buf)) >= sizeof(struct sphdr)) {
        !           639: #ifdef DEBUG
        !           640:                        BUGOUT("cleanup -- got packet");
        !           641: #endif
        !           642:                        if ((!(si->sp_cc & SP_OB))
        !           643:                            && si->sp_dt == SPPSST_ENDREPLY) {
        !           644:                                changeSPPopts(net, SPPSST_ENDREPLY, 1);
        !           645:                                write(net, &our_sphdr, sizeof(our_sphdr));
        !           646: #ifdef DEBUG
        !           647:                                BUGOUT("cleanup -- wrote ENDREPLY");
        !           648: #endif
        !           649:                                sleep(1);
        !           650:                                changeSPPopts(net,0,0);
        !           651:                                ioctl(net, FIONBIO, &off);
        !           652:                                rmut();
        !           653:                                vhangup();      /* XXX */
        !           654:                                return;
        !           655:                        }
        !           656:                        /* loop: ignore everything except ENDREPLY */
        !           657:                        fdmask = 1<<net;
        !           658:                        timeout.tv_sec = 10;
        !           659:                }
        !           660:                /* timed out or read failed */
        !           661:                changeSPPopts(net, SPPSST_ENDREPLY, 1);
        !           662:                write(net, &our_sphdr, sizeof(our_sphdr));
        !           663:                sleep(1);
        !           664:        }
        !           665:        shutdown(net, 1);
        !           666:        close(net);
        !           667:        rmut();
        !           668:        vhangup();      /* XXX */
        !           669: }
        !           670: 
        !           671: /*
        !           672:  * SIGCHLD interrupt handler
        !           673:  */
        !           674: childdied()
        !           675: {
        !           676: #ifdef DEBUG
        !           677:        BUGOUT("child died");
        !           678: #endif
        !           679:        cleanup();
        !           680:        longjmp(childdiedbuf, -1);
        !           681: }
        !           682: 
        !           683: changeSPPopts(s, stream, eom)
        !           684:        int s;                  /* SPP socket */
        !           685:        u_char stream;          /* datastream type */
        !           686:        char eom;               /* Boolean EOM */
        !           687: {
        !           688:        our_sphdr.sp_dt = stream;
        !           689:        our_sphdr.sp_cc = (eom ? SP_EM : 0);
        !           690: }
        !           691: 
        !           692: 
        !           693: #include <utmp.h>
        !           694: 
        !           695: struct utmp wtmp;
        !           696: char   wtmpf[] = "/usr/adm/wtmp";
        !           697: char   utmp[] = "/etc/utmp";
        !           698: #define SCPYN(a, b)    strncpy(a, b, sizeof (a))
        !           699: #define SCMPN(a, b)    strncmp(a, b, sizeof (a))
        !           700: 
        !           701: rmut()
        !           702: {
        !           703:        register f;
        !           704:        int found = 0;
        !           705: 
        !           706:        f = open(utmp, 2);
        !           707:        if (f >= 0) {
        !           708:                while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) {
        !           709:                        if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0)
        !           710:                                continue;
        !           711:                        lseek(f, -(long)sizeof (wtmp), 1);
        !           712:                        SCPYN(wtmp.ut_name, "");
        !           713:                        SCPYN(wtmp.ut_host, "");
        !           714:                        time(&wtmp.ut_time);
        !           715:                        write(f, (char *)&wtmp, sizeof (wtmp));
        !           716:                        found++;
        !           717:                }
        !           718:                close(f);
        !           719:        }
        !           720:        if (found) {
        !           721:                f = open(wtmpf, 1);
        !           722:                if (f >= 0) {
        !           723:                        SCPYN(wtmp.ut_line, line+5);
        !           724:                        SCPYN(wtmp.ut_name, "");
        !           725:                        SCPYN(wtmp.ut_host, "");
        !           726:                        time(&wtmp.ut_time);
        !           727:                        lseek(f, (long)0, 2);
        !           728:                        write(f, (char *)&wtmp, sizeof (wtmp));
        !           729:                        close(f);
        !           730:                }
        !           731:        }
        !           732:        chmod(line, 0666);
        !           733:        chown(line, 0, 0);
        !           734:        line[strlen("/dev/")] = 'p';
        !           735:        chmod(line, 0666);
        !           736:        chown(line, 0, 0);
        !           737: }
        !           738: 
        !           739: /*
        !           740:  * Convert network-format xns address
        !           741:  * to ascii
        !           742:  * --Replace this with a clearinghouse name lookup someday.
        !           743:  */
        !           744: char *
        !           745: wsname(addr)
        !           746:        struct ns_addr addr;
        !           747: {
        !           748:        static char b[50];
        !           749:        char temp[10];
        !           750:        int i;
        !           751: 
        !           752:        /* net */
        !           753:        sprintf(b, "%D.", ntohl(ns_netof(addr)));
        !           754:        /* skip leading zeros */
        !           755:        for(i=0; (addr.x_host.c_host[i] == (char) 0); i++) ;
        !           756:        /* print the rest */
        !           757:        for(; i < 6; i++) {
        !           758:                sprintf(temp,"%x", addr.x_host.c_host[i]);
        !           759:                strcat(b, temp);
        !           760:                if(i != 5) strcat(b, ":");
        !           761:        }
        !           762:        return (b);
        !           763: }
        !           764: 
        !           765: /*
        !           766:   * generate an xns address that "DE" can parse.
        !           767:   * This goes in the environment.  Should be the same as above
        !           768:   */
        !           769: char *
        !           770: xntoa(addr)
        !           771:        struct ns_addr addr;
        !           772: {
        !           773:        static char b[50];
        !           774:        char temp[10];
        !           775:        int i;
        !           776: 
        !           777:        /* net */
        !           778:        sprintf(b, "%X#", ntohl(ns_netof(addr)));
        !           779:        /* print the rest */
        !           780:        for(i=0; i < 6; i++) {
        !           781:                sprintf(temp,"%x", addr.x_host.c_host[i]);
        !           782:                strcat(b, temp);
        !           783:                if(i != 5) strcat(b, ".");
        !           784:        }
        !           785:        return (b);
        !           786: }
        !           787: 
        !           788: #ifdef DEBUG
        !           789: BUGOUT(str,a,b,c,d,e,f,g,h)
        !           790:        char *str;
        !           791: {
        !           792:        FILE *fd;
        !           793:        fd = fopen("/tmp/GAP3d.log","a");
        !           794:        fprintf(fd,str,a,b,c,d,e,f,g,h);
        !           795:        putc('\n',fd);
        !           796:        fclose(fd);
        !           797: }
        !           798: #endif

unix.superglobalmegacorp.com

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