Annotation of 43BSD/contrib/xns/examples/gap/gaptelnetd.c, revision 1.1.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.