Annotation of 43BSDTahoe/new/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.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.