Annotation of 43BSDTahoe/new/xns/examples/gap/gaptelnetd.c, revision 1.1

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

unix.superglobalmegacorp.com

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