Annotation of 43BSDReno/contrib/isode-beta/ssap/ssaprovider.c, revision 1.1

1.1     ! root        1: /* ssaprovider.c - implement the session protocol */
        !             2: 
        !             3: #ifndef        lint
        !             4: static char *rcsid = "$Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $";
        !             5: #endif
        !             6: 
        !             7: /* 
        !             8:  * $Header: /f/osi/ssap/RCS/ssaprovider.c,v 7.1 89/11/30 23:51:19 mrose Exp $
        !             9:  *
        !            10:  *
        !            11:  * $Log:       ssaprovider.c,v $
        !            12:  * Revision 7.1  89/11/30  23:51:19  mrose
        !            13:  * touch-up
        !            14:  * 
        !            15:  * Revision 7.0  89/11/23  22:25:45  mrose
        !            16:  * Release 6.0
        !            17:  * 
        !            18:  */
        !            19: 
        !            20: /*
        !            21:  *                               NOTICE
        !            22:  *
        !            23:  *    Acquisition, use, and distribution of this module and related
        !            24:  *    materials are subject to the restrictions of a license agreement.
        !            25:  *    Consult the Preface in the User's Manual for the full terms of
        !            26:  *    this agreement.
        !            27:  *
        !            28:  */
        !            29: 
        !            30: 
        !            31: /* LINTLIBRARY */
        !            32: 
        !            33: #include <stdio.h>
        !            34: #include <signal.h>
        !            35: #include "spkt.h"
        !            36: #include "tailor.h"
        !            37: 
        !            38: /*    DATA */
        !            39: 
        !            40: static int  once_only = 0;
        !            41: static struct ssapblk ssapque;
        !            42: static struct ssapblk *SHead = &ssapque;
        !            43: 
        !            44: 
        !            45: int    TDATAser (), TDISCser ();
        !            46: 
        !            47: 
        !            48: /*    S-DATA.REQUEST */
        !            49: 
        !            50: int    SDataRequest (sd, data, cc, si)
        !            51: int    sd;
        !            52: char   *data;
        !            53: int    cc;
        !            54: struct SSAPindication *si;
        !            55: {
        !            56:     SBV            smask;
        !            57:     int     result;
        !            58:     struct udvec uvs[2];
        !            59:     register struct udvec *uv = uvs;
        !            60:     register struct ssapblk *sb;
        !            61: 
        !            62:     missingP (data);
        !            63:     if (cc <= 0)
        !            64:        return ssaplose (si, SC_PARAMETER, NULLCP,
        !            65:                    "illegal value for SSDU length (%d)", cc);
        !            66:     missingP (si);
        !            67: 
        !            68:     smask = sigioblock ();
        !            69: 
        !            70:     ssapPsig (sb, sd);
        !            71: 
        !            72:     uv -> uv_base = data, uv -> uv_len = cc, uv++;
        !            73:     uv -> uv_base = NULL;
        !            74: 
        !            75:     result = SDataRequestAux (sb, SPDU_DT, uvs, si);
        !            76: 
        !            77:     (void) sigiomask (smask);
        !            78: 
        !            79:     return result;
        !            80: }
        !            81: 
        !            82: /*    S-WRITE.REQUEST (pseudo; write user data vectors) */
        !            83: 
        !            84: int    SWriteRequest (sd, typed, uv, si)
        !            85: int    sd;
        !            86: int    typed;
        !            87: struct udvec *uv;
        !            88: struct SSAPindication *si;
        !            89: {
        !            90:     SBV            smask;
        !            91:     int     result;
        !            92:     register struct ssapblk *sb;
        !            93: 
        !            94:     missingP (uv);
        !            95:     missingP (si);
        !            96: 
        !            97:     smask = sigioblock ();
        !            98: 
        !            99:     ssapPsig (sb, sd);
        !           100: 
        !           101:     result = SDataRequestAux (sb, typed ? SPDU_TD : SPDU_DT, uv, si);
        !           102: 
        !           103:     (void) sigiomask (smask);
        !           104: 
        !           105:     return result;
        !           106: }
        !           107: 
        !           108: /*  */
        !           109: 
        !           110: #define        NSPUV   12      /* really should be MSG_MAXIOVLEN - 4 */
        !           111: 
        !           112: 
        !           113: int    SDataRequestAux (sb, code, uv, si)
        !           114: register struct ssapblk *sb;
        !           115: int    code;
        !           116: register struct udvec *uv;
        !           117: struct SSAPindication *si;
        !           118: {
        !           119:     int     begin,
        !           120:            cc,             
        !           121:             j,
        !           122:            len,
        !           123:            n,
        !           124:             result;
        !           125:     register char *bp,
        !           126:                  *ep;
        !           127:     register struct ssapkt *s;
        !           128:     struct TSAPdisconnect   tds;
        !           129:     register struct TSAPdisconnect *td = &tds;
        !           130:     struct udvec vvs[NSPUV];
        !           131:     register struct udvec  *vv,
        !           132:                           *wv;
        !           133:     struct udvec *xv;
        !           134: 
        !           135:     switch (code) {
        !           136:        case SPDU_DT: 
        !           137:            if ((sb -> sb_requirements & SR_DAT_EXISTS)
        !           138:                    && !(sb -> sb_owned & ST_DAT_TOKEN))
        !           139:                return ssaplose (si, SC_OPERATION, NULLCP,
        !           140:                        "data token not owned by you");
        !           141:            break;
        !           142: 
        !           143:        case SPDU_TD: 
        !           144:            if (!(sb -> sb_requirements & SR_TYPEDATA))
        !           145:                return ssaplose (si, SC_OPERATION, NULLCP,
        !           146:                        "typed data service unavailable");
        !           147:            break;
        !           148:     }
        !           149: 
        !           150:     n = 0;
        !           151:     for (vv = uv; vv -> uv_base; vv++)
        !           152:        n += vv -> uv_len;
        !           153:     if (n == 0)
        !           154:        return ssaplose (si, SC_PARAMETER, NULLCP, "zero-length SSDU");
        !           155:     
        !           156:     ep = (bp = uv -> uv_base) + (cc = uv -> uv_len);
        !           157:     begin = 1;
        !           158:     while (uv -> uv_base) {
        !           159:        len = sb -> sb_tsdu_us ? min (n, sb -> sb_tsdu_us - SSDU_MAGIC) : n;
        !           160:        vv = vvs;
        !           161:        vvs[0].uv_base = vvs[1].uv_base = NULL;
        !           162:        vvs[1].uv_inline = 0;
        !           163: 
        !           164:        if (code == SPDU_DT) {
        !           165:            if ((s = newspkt (SPDU_GT)) == NULL)
        !           166:                return ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
        !           167:            s -> s_mask |= SMASK_SPDU_GT;
        !           168: 
        !           169:            if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
        !           170:                (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
        !           171:                goto out1;
        !           172:            }
        !           173:            freespkt (s);
        !           174:            s = NULL;
        !           175:            vv++;
        !           176:        }
        !           177: 
        !           178:        xv = vv++;
        !           179: 
        !           180:        wv = vvs + NSPUV - 1;
        !           181:        for (; len > 0 && vv < wv; len -= j) {
        !           182:            j = min (cc, len);
        !           183:            vv -> uv_base = bp, vv -> uv_len = j, vv -> uv_inline = 1, vv++;
        !           184:            bp += j, cc -= j, n -= j;
        !           185: 
        !           186:            if (bp >= ep) {
        !           187:                if ((bp = (++uv) -> uv_base) == NULL)
        !           188:                    break;
        !           189:                ep = bp + (cc = uv -> uv_len);
        !           190:            }
        !           191:        }
        !           192:        if (!sb -> sb_tsdu_us && uv -> uv_base) {
        !           193:            (void) ssaplose (si, SC_PARAMETER, NULLCP,
        !           194:                             "too many vector entries in SDU");
        !           195:            goto out2;
        !           196:        }
        !           197:        vv -> uv_base = NULL;
        !           198: 
        !           199:        vv = xv;
        !           200:        if ((s = newspkt (code)) == NULL) {
        !           201:            (void) ssaplose (si, SC_CONGEST, NULLCP, "out of memory");
        !           202:            goto out2;
        !           203:        }
        !           204:        if (sb -> sb_tsdu_us) {
        !           205:            s -> s_mask |= SMASK_ENCLOSE;
        !           206:            if (begin) {
        !           207:                s -> s_enclose |= ENCL_BEGIN;
        !           208:                begin = 0;
        !           209:            }       
        !           210:            if (uv -> uv_base == NULL)
        !           211:                s -> s_enclose |= ENCL_END;
        !           212:        }
        !           213:        if (spkt2tsdu (s, &vv -> uv_base, &vv -> uv_len) == NOTOK) {
        !           214:            (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
        !           215:            goto out3;
        !           216:        }
        !           217:        freespkt (s);
        !           218:        s = NULL;
        !           219: 
        !           220:        if ((result = TWriteRequest (sb -> sb_fd, vvs, td)) == NOTOK)
        !           221:            (void) ts2sslose (si, "TWriteRequest", td);
        !           222: 
        !           223:        free (vvs[0].uv_base);
        !           224:        if (code == SPDU_DT)
        !           225:            free (vvs[1].uv_base);
        !           226: 
        !           227:        if (result == NOTOK)
        !           228:            return NOTOK;
        !           229:     }
        !           230:     return OK;
        !           231: 
        !           232: out3: ;
        !           233:     if (vvs[1].uv_base && !vvs[1].uv_inline)
        !           234:        free (vvs[1].uv_base);
        !           235: out2: ;
        !           236:     if (vvs[0].uv_base)
        !           237:        free (vvs[0].uv_base);
        !           238: out1: ;
        !           239:     freespkt (s);
        !           240: 
        !           241:     return NOTOK;
        !           242: }
        !           243: 
        !           244: /*    S-READ.REQUEST (pseudo; synchronous read) */
        !           245: 
        !           246: int    SReadRequest (sd, sx, secs, si)
        !           247: int    sd;
        !           248: struct SSAPdata *sx;
        !           249: int    secs;
        !           250: struct SSAPindication *si;
        !           251: {
        !           252:     SBV            smask;
        !           253:     int     result;
        !           254:     register struct ssapblk *sb;
        !           255: 
        !           256:     missingP (sx);
        !           257:     missingP (si);
        !           258: 
        !           259:     smask = sigioblock ();
        !           260: 
        !           261:     if ((sb = findsblk (sd)) == NULL) {
        !           262:        (void) sigiomask (smask);
        !           263:        return ssaplose (si, SC_PARAMETER, NULLCP, "invalid session descriptor");
        !           264:     }
        !           265:     if (!(sb -> sb_flags & SB_CONN)) {
        !           266:        (void) sigiomask (smask); 
        !           267:        return ssaplose (si, SC_PARAMETER, NULLCP, 
        !           268:                            "session descriptor not connected"); 
        !           269:     } 
        !           270:     if (sb -> sb_flags & SB_FINN) { 
        !           271:        (void) sigiomask (smask); 
        !           272:        return ssaplose (si, SC_OPERATION, NULLCP, 
        !           273:                            "session descriptor finishing"); 
        !           274:     } 
        !           275: 
        !           276:     result = SReadRequestAux (sb, sx, secs, si, 0, NULLTX);
        !           277: 
        !           278:     (void) sigiomask (smask);
        !           279: 
        !           280:     return result;
        !           281: }
        !           282: 
        !           283: /*  */
        !           284: 
        !           285: static int  SReadRequestAux (sb, sx, secs, si, async, tx)
        !           286: register struct ssapblk *sb;
        !           287: register struct SSAPdata *sx;
        !           288: int    secs;
        !           289: struct SSAPindication *si;
        !           290: int    async;
        !           291: struct TSAPdata *tx;
        !           292: {
        !           293:     int     eot;
        !           294:     char    tokens;
        !           295:     register struct ssapkt *s;
        !           296: 
        !           297:     bzero ((char *) sx, sizeof *sx);
        !           298:     sx -> sx_qbuf.qb_forw = sx -> sx_qbuf.qb_back = &sx -> sx_qbuf;
        !           299:     bzero ((char *) si, sizeof *si);
        !           300: 
        !           301:     for (; s = sb2spkt (sb, si, secs, tx); tx = NULLTX) {
        !           302:        if (!(s -> s_mask & SMASK_SPDU_EXPD))
        !           303:            switch (sb -> sb_pr) {
        !           304:                case SPDU_PR:
        !           305:                    break;
        !           306: 
        !           307:                case SPDU_MAA:
        !           308:                    if (s -> s_code == SPDU_MAA)
        !           309:                        sb -> sb_pr = SPDU_PR;
        !           310:                    break;
        !           311: 
        !           312:                case SPDU_RS:
        !           313:                    switch (s -> s_code) {
        !           314:                        case SPDU_AB:
        !           315: #ifdef notdef
        !           316:                        case SPDU_AI:   /* aka SPDU_AB */
        !           317: #endif
        !           318:                            if (s -> s_mask & SMASK_SPDU_AB)
        !           319:                                break;  /* else fall */
        !           320:                        case SPDU_AD:
        !           321:                        case SPDU_RS:
        !           322:                            sb -> sb_pr = SPDU_PR;
        !           323:                            break;
        !           324: 
        !           325:                        default:
        !           326:                            goto drop_it;
        !           327:                    }
        !           328:                    break;
        !           329: 
        !           330:                case SPDU_RA:
        !           331:                    switch (s -> s_code) {
        !           332:                        case SPDU_AB:
        !           333:                            break;
        !           334: 
        !           335:                        case SPDU_AA:
        !           336: #ifdef notdef
        !           337:                        case SPDU_AIA:  /* aka SPDU_AA */
        !           338: #endif
        !           339:                            if (s -> s_mask & SMASK_SPDU_AA)
        !           340:                                break;  /* else fall */
        !           341:                        case SPDU_ADA:
        !           342:                        case SPDU_RA:
        !           343:                            sb -> sb_pr = SPDU_PR;
        !           344:                            break;
        !           345: 
        !           346:                        default:
        !           347: drop_it: ;
        !           348:                            SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !           349:                                  ("discarding 0x%x SPDU", s -> s_code));
        !           350:                            freespkt (s);
        !           351:                            goto spin;
        !           352:                    }
        !           353:                    break;
        !           354: 
        !           355:                case SPDU_AB:
        !           356:                    if (s -> s_code != SPDU_AB)
        !           357:                        goto drop_it;
        !           358:                    sb -> sb_pr = SPDU_PR;
        !           359:                    break;
        !           360: 
        !           361:                default:
        !           362:                    break;
        !           363:            }
        !           364: 
        !           365:        if (sb -> sb_flags & (SB_RS | SB_AI))
        !           366:            switch (s -> s_code) {
        !           367:                case SPDU_PR:
        !           368:                    switch (s -> s_pr_type) {
        !           369:                        case PR_RS:
        !           370:                        case PR_RA:
        !           371:                            break;
        !           372:                        default:
        !           373:                            goto drop_it;
        !           374:                    }
        !           375:                    break;
        !           376: 
        !           377:                case SPDU_RS:
        !           378:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
        !           379:                                sb -> sb_rs, sb -> sb_rsn,
        !           380:                                (int) s -> s_rs_type, (long) s -> s_rs_serial)
        !           381:                            != NOTOK)
        !           382:                        goto drop_it;
        !           383:                    break;
        !           384: 
        !           385:                case SPDU_RA:
        !           386:                    break;
        !           387:                  
        !           388:                case SPDU_AD:
        !           389:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
        !           390:                                sb -> sb_rs, sb -> sb_rsn, SYNC_DISC, 0L)
        !           391:                            != NOTOK)
        !           392:                        goto drop_it;
        !           393:                    break;
        !           394: 
        !           395:                case SPDU_AB:
        !           396: #ifdef notdef
        !           397:                case SPDU_AI:   /* aka SPDU_AB */
        !           398: #endif
        !           399:                    if (s -> s_mask & SMASK_SPDU_AB)
        !           400:                        break;
        !           401:                    if (SDoCollideAux (sb -> sb_flags & SB_INIT ? 1 : 0,
        !           402:                                sb -> sb_rs, sb -> sb_rsn, SYNC_INTR, 0L)
        !           403:                            != NOTOK)
        !           404:                        goto drop_it;
        !           405:                    break;
        !           406:            }
        !           407:        
        !           408:        if (sb -> sb_flags & (SB_ED | SB_ERACK))
        !           409:            switch (s -> s_code) {
        !           410:                case SPDU_AB:
        !           411:                    break;
        !           412: 
        !           413:                case SPDU_MAP:
        !           414:                case SPDU_MIP:
        !           415:                    if (sb -> sb_flags & SB_ED)
        !           416:                        break;
        !           417:                    goto drop_it;
        !           418: 
        !           419:                case SPDU_PR:
        !           420:                    if (s -> s_pr_type == PR_RS)
        !           421:                        break;
        !           422:                    goto drop_it;
        !           423: 
        !           424:                case SPDU_GT:
        !           425:                    if ((s -> s_mask & SMASK_SPDU_GT)
        !           426:                            && (s -> s_mask & SMASK_GT_TOKEN)
        !           427:                            && (s -> s_gt_token & ST_DAT_TOKEN))
        !           428:                        break;  /* else fall */
        !           429: 
        !           430:                default:
        !           431:                    goto drop_it;
        !           432:            }
        !           433: 
        !           434:        if (sb -> sb_len > 0)
        !           435:            switch (s -> s_code) {
        !           436:                case SPDU_PT:
        !           437:                case SPDU_EX:
        !           438:                    break;
        !           439: 
        !           440:                case SPDU_PR:
        !           441:                    if (s -> s_pr_type != PR_RS)
        !           442:                        break;
        !           443:                case SPDU_RS:
        !           444:                case SPDU_ER:
        !           445:                case SPDU_ED:
        !           446:                case SPDU_AD:
        !           447: #ifdef notdef
        !           448:                case SPDU_AI:   /* aka SPDU_AB */
        !           449: #endif
        !           450:                case SPDU_AB:
        !           451:                    SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !           452:                          ("flush partially assembled (T))SSDU"));
        !           453:                    QBFREE (&sb -> sb_qbuf);
        !           454:                    sb -> sb_len = 0;
        !           455:                    break;
        !           456: 
        !           457:                case SPDU_GT:
        !           458:                    if (s -> s_mask & SMASK_SPDU_GT)
        !           459:                        break;  /* else SPDU_DT */
        !           460:                default:
        !           461:                    if (sb -> sb_code == s -> s_code)
        !           462:                        break;
        !           463:                    (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           464:                            "session protocol mangled: expecting 0x%x, got 0x%x during segmentation",
        !           465:                            sb -> sb_code, s -> s_code);
        !           466:                    goto out;
        !           467:            }
        !           468: 
        !           469: /* allows AB SPDUs to have 512, not 9, octets (which is fine by me) */
        !           470:        if (s -> s_ulen > CN_SIZE && sb -> sb_version < SB_VRSN2) {
        !           471:            (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           472:                             "too much user data (%d) in SPDU 0x%x",
        !           473:                             s -> s_ulen, s -> s_code);
        !           474:            goto out;
        !           475:        }
        !           476: 
        !           477:        if ((s -> s_mask & SMASK_ENCLOSE)
        !           478:                && (s -> s_code != SPDU_DT || (s -> s_mask & SMASK_SPDU_GT))
        !           479:                && s -> s_code != SPDU_TD) {
        !           480:            if (sb -> sb_version < SB_VRSN2) {
        !           481:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           482:                                 "unexpected segmentation for SPDU 0x%x",
        !           483:                                 s -> s_code);
        !           484:                goto out;
        !           485:            }
        !           486: 
        !           487: /* XXX: in practice, I don't think this is unreasonable.  It is
        !           488:        however not too restrictive */
        !           489: 
        !           490:            if (s -> s_enclose != ENCL_MASK) {
        !           491:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           492:                                 "non-trivial segmentation (0x%x) for SPDU 0x%x",
        !           493:                                 s -> s_enclose, s -> s_code);
        !           494:                goto out;
        !           495:            }
        !           496:        }
        !           497: 
        !           498:        switch (s -> s_code) {
        !           499:            case SPDU_PT: 
        !           500:                if (sb -> sb_flags & SB_GTC) {
        !           501:                    freespkt (s);
        !           502:                    goto spin;
        !           503:                }
        !           504:                tokens = 0;
        !           505:                if (s -> s_mask & SMASK_PT_TOKEN) {
        !           506: #define        dotoken(requires,shift,bit,type) \
        !           507: { \
        !           508:                    if ((sb -> sb_requirements & requires) \
        !           509:                            && (s -> s_pt_token & bit)) \
        !           510:                        tokens |= bit; \
        !           511: }
        !           512:                        dotokens ();
        !           513: #undef dotoken
        !           514:                }
        !           515:                si -> si_type = SI_TOKEN;
        !           516:                {
        !           517:                    register struct SSAPtoken *st = &si -> si_token;
        !           518: 
        !           519:                    st -> st_type = ST_PLEASE;
        !           520:                    st -> st_tokens = tokens;
        !           521:                    st -> st_owned = sb -> sb_owned;
        !           522:                    copySPKTdata (s, st);
        !           523:                }
        !           524:                freespkt (s);
        !           525:                return DONE;
        !           526: 
        !           527:            case SPDU_GT: 
        !           528:                if (s -> s_mask & SMASK_SPDU_GT) {
        !           529:                    if (sb -> sb_flags & SB_GTC) {
        !           530:                        freespkt (s);
        !           531:                        goto spin;
        !           532:                    }
        !           533:                    tokens = 0;
        !           534:                    if (s -> s_mask & SMASK_GT_TOKEN) {
        !           535: #define        dotoken(requires,shift,bit,type) \
        !           536: { \
        !           537:                        if ((sb -> sb_requirements & requires) \
        !           538:                            && (s -> s_gt_token & bit)) \
        !           539:                                sb -> sb_owned |= bit, tokens |= bit; \
        !           540: }
        !           541:                        dotokens ();
        !           542: #undef dotoken
        !           543:                    }
        !           544:                    freespkt (s);
        !           545:                    if (tokens & ST_DAT_TOKEN)
        !           546:                        sb -> sb_flags &= ~(SB_ED | SB_ERACK);
        !           547:                    si -> si_type = SI_TOKEN;
        !           548:                    {
        !           549:                        register struct SSAPtoken  *st = &si -> si_token;
        !           550: 
        !           551:                        st -> st_type = ST_GIVE;
        !           552:                        st -> st_tokens = tokens;
        !           553:                        st -> st_owned = sb -> sb_owned;
        !           554:                    }
        !           555:                    return DONE;
        !           556:                }               /* else fall for case SPDU_DT: */
        !           557: #ifdef notdef
        !           558:            case SPDU_DT:
        !           559: #endif
        !           560:            case SPDU_TD:
        !           561:                sb -> sb_code = s -> s_code;
        !           562:                if (sb -> sb_tsdu_them) {
        !           563:                    if (!(s -> s_mask & SMASK_ENCLOSE)) {
        !           564:                        (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           565:                                "no segmentation information");
        !           566:                        break;
        !           567:                    }
        !           568:                    if ((s -> s_enclose & ENCL_BEGIN)
        !           569:                            ? sb -> sb_len > 0 : sb -> sb_len == 0) {
        !           570:                        (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !           571:                                "segmentation mismatch");
        !           572:                        break;
        !           573:                    }
        !           574:                    eot = s -> s_enclose & ENCL_END;
        !           575:                }
        !           576:                else
        !           577:                    eot = 1;
        !           578:                if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
        !           579:                    sb -> sb_qbuf.qb_back -> qb_forw = s -> s_qbuf.qb_forw;
        !           580:                    s -> s_qbuf.qb_forw -> qb_back = sb -> sb_qbuf.qb_back;
        !           581:                    s -> s_qbuf.qb_back -> qb_forw = &sb -> sb_qbuf;
        !           582:                    sb -> sb_qbuf.qb_back = s -> s_qbuf.qb_back;
        !           583:                    sb -> sb_len += s -> s_qlen;
        !           584:                    s -> s_qbuf.qb_forw =
        !           585:                            s -> s_qbuf.qb_back = &s -> s_qbuf;
        !           586:                    s -> s_qlen = 0;
        !           587:                }
        !           588:                if (!eot && (s -> s_code == SPDU_DT) && sb -> sb_spdu) {
        !           589:                    freespkt (sb -> sb_spdu);
        !           590:                    sb -> sb_spdu = NULL;
        !           591:                }
        !           592:                freespkt (s);
        !           593:                if (!eot)
        !           594:                    goto spin;
        !           595:                sx -> sx_type = sb -> sb_code == SPDU_DT ? SX_NORMAL
        !           596:                                    : SX_TYPED;
        !           597:                if (sb -> sb_qbuf.qb_forw != &sb -> sb_qbuf) {
        !           598:                    sx -> sx_qbuf = sb -> sb_qbuf;/* struct copy */
        !           599:                    sx -> sx_qbuf.qb_forw -> qb_back =
        !           600:                            sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
        !           601:                    sx -> sx_cc = sb -> sb_len;
        !           602:                    sb -> sb_qbuf.qb_forw =
        !           603:                            sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
        !           604:                    sb -> sb_len = 0;
        !           605:                }
        !           606:                return OK;
        !           607: 
        !           608:            case SPDU_EX: 
        !           609:                if (sb -> sb_pr != SPDU_PR) {
        !           610:                    SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !           611:                          ("buffering XSDU during preparation"));
        !           612:                    if (sb -> sb_xspdu) {
        !           613:                        (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
        !           614:                                "unable to buffer second XSDU");
        !           615:                        break;
        !           616:                    }
        !           617:                    sb -> sb_xspdu = s;
        !           618:                    goto spin;
        !           619:                }
        !           620:                sx -> sx_type = SX_EXPEDITED;
        !           621:                if (s -> s_qbuf.qb_forw != &s -> s_qbuf) {
        !           622:                    sx -> sx_qbuf = s -> s_qbuf;/* struct copy */
        !           623:                    sx -> sx_qbuf.qb_forw -> qb_back =
        !           624:                            sx -> sx_qbuf.qb_back -> qb_forw = &sx -> sx_qbuf;
        !           625:                    sx -> sx_cc = s -> s_qlen;
        !           626:                    s -> s_qbuf.qb_forw =
        !           627:                            s -> s_qbuf.qb_back = &s -> s_qbuf;
        !           628:                    s -> s_qlen = 0;
        !           629:                }
        !           630:                freespkt (s);
        !           631:                return OK;
        !           632: 
        !           633:            case SPDU_CD:
        !           634:            case SPDU_CDA:
        !           635:                if (s -> s_code == SPDU_CD) {
        !           636:                    sb -> sb_flags |= SB_CDA;
        !           637:                    sx -> sx_type = SX_CAPDIND;
        !           638:                }
        !           639:                else {
        !           640:                    sb -> sb_flags &= ~SB_CD;
        !           641:                    sx -> sx_type = SX_CAPDCNF;
        !           642:                }
        !           643:                if (s -> s_udata) {
        !           644:                    register struct qbuf *qb;
        !           645: 
        !           646:                    qb = (struct qbuf *)
        !           647:                            malloc (sizeof *qb + (unsigned) s -> s_ulen);
        !           648:                    if (qb == NULL) {
        !           649:                        (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
        !           650:                                    "out of memory");
        !           651:                        break;
        !           652:                    }
        !           653:                    bcopy (s -> s_udata, qb -> qb_data = qb -> qb_base,
        !           654:                            qb -> qb_len = s -> s_ulen);
        !           655:                    insque (qb, &sx -> sx_qbuf);
        !           656:                    sx -> sx_cc = s -> s_ulen;
        !           657:                }
        !           658:                freespkt (s);
        !           659:                return OK;
        !           660: 
        !           661:            case SPDU_GTC:
        !           662:                if (sb -> sb_flags & SB_Vact) {
        !           663:                    freespkt (s);
        !           664:                    goto spin;
        !           665:                }
        !           666: #define        dotoken(requires,shift,bit,type) \
        !           667: { \
        !           668:                if (sb -> sb_requirements & requires) \
        !           669:                    sb -> sb_owned |= bit; \
        !           670: }
        !           671:                dotokens ();
        !           672: #undef dotoken
        !           673:                freespkt (s);
        !           674:                if ((s = newspkt (SPDU_GTA)) == NULL) {
        !           675:                    (void) spktlose (sb -> sb_fd, si, SC_CONGEST, NULLCP,
        !           676:                            "out of memory");
        !           677:                    break;
        !           678:                }
        !           679:                if (spkt2sd (s, sb -> sb_fd, 0, si) == NOTOK)
        !           680:                    break;
        !           681:                freespkt (s);
        !           682:                si -> si_type = SI_TOKEN;
        !           683:                {
        !           684:                    register struct SSAPtoken  *st = &si -> si_token;
        !           685: 
        !           686:                    st -> st_type = ST_CONTROL;
        !           687:                    st -> st_tokens = st -> st_owned = sb -> sb_owned;
        !           688:                }
        !           689:                return DONE;
        !           690: 
        !           691:            case SPDU_GTA:
        !           692:                if (!(sb -> sb_flags & SB_GTC)) {
        !           693:                    freespkt (s);
        !           694:                    goto spin;
        !           695:                }
        !           696:                sb -> sb_flags &= ~SB_GTC;
        !           697: spin: ;
        !           698:                if (!async || sb -> sb_spdu)
        !           699:                    continue;
        !           700:                si -> si_type = SI_DATA;
        !           701:                {
        !           702:                    register struct SSAPdata *sk = &si -> si_data;
        !           703: 
        !           704:                    bzero ((char *) sk, sizeof *sk);
        !           705:                    sk -> sx_qbuf.qb_forw = sk -> sx_qbuf.qb_back =
        !           706:                        &sk -> sx_qbuf;
        !           707:                }
        !           708:                return DONE;
        !           709: 
        !           710:            case SPDU_MAP:
        !           711: #ifdef notdef
        !           712:            case SPDU_AE:       /* aka SPDU_MAP */
        !           713: #endif
        !           714:                if (sb -> sb_V_M != s -> s_map_serial) {
        !           715:                    freespkt (s);
        !           716:                    goto spin;
        !           717:                }
        !           718:                if (!(s -> s_mask & SMASK_MAP_SYNC)
        !           719:                        || !(s -> s_map_sync & MAP_SYNC_NOEND))
        !           720:                    goto spdu_ae;
        !           721:                if (!(sb -> sb_flags & SB_Vsc))
        !           722:                    sb -> sb_V_A = sb -> sb_V_M;
        !           723:                sb -> sb_V_M++;
        !           724:                if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
        !           725:                    freespkt (s);
        !           726:                    goto spin;
        !           727:                }
        !           728:                if (sb -> sb_requirements & SR_ACTIVITY)
        !           729:                    sb -> sb_flags |= SB_Vnextact;
        !           730:                sb -> sb_flags |= SB_MAA;
        !           731:                si -> si_type = SI_SYNC;
        !           732:                {
        !           733:                    register struct SSAPsync *sn = &si -> si_sync;
        !           734: 
        !           735:                    sn -> sn_type = SN_MAJORIND;
        !           736:                    sn -> sn_ssn = s -> s_map_serial;
        !           737:                    copySPKTdata (s, sn);
        !           738:                }
        !           739:                freespkt (s);
        !           740:                return DONE;
        !           741: 
        !           742:            case SPDU_MAA:
        !           743: #ifdef notdef
        !           744:            case SPDU_AEA:      /* aka SPDU_MAA */
        !           745: #endif
        !           746:                if (sb -> sb_V_M != s -> s_maa_serial + 1) {
        !           747:                    freespkt (s);
        !           748:                    goto spin;
        !           749:                }
        !           750:                sb -> sb_V_A = sb -> sb_V_R = sb -> sb_V_M;
        !           751:                if (sb -> sb_requirements & SR_ACTIVITY)
        !           752:                    if (sb -> sb_flags & SB_Vnextact)
        !           753:                        sb -> sb_flags |= SB_Vact;
        !           754:                    else
        !           755:                        sb -> sb_flags &= ~SB_Vact;
        !           756:                sb -> sb_flags &= ~SB_MAP;
        !           757:                if (sb -> sb_flags & SB_AE) {
        !           758:                    sb -> sb_flags &= ~SB_AE;
        !           759:                    si -> si_type = SI_ACTIVITY;
        !           760:                    {
        !           761:                        register struct SSAPactivity *sv = &si -> si_activity;
        !           762: 
        !           763:                        sv -> sv_type = SV_ENDCNF;
        !           764:                        sv -> sv_ssn = s -> s_maa_serial;
        !           765:                        copySPKTdata (s, sv);
        !           766:                    }
        !           767:                }
        !           768:                else {
        !           769:                    si -> si_type = SI_SYNC;
        !           770:                    {
        !           771:                        register struct SSAPsync *sn = &si -> si_sync;
        !           772: 
        !           773:                        sn -> sn_type = SN_MAJORCNF;
        !           774:                        sn -> sn_ssn = s -> s_maa_serial;
        !           775:                        copySPKTdata (s, sn);
        !           776:                    }
        !           777:                }
        !           778:                freespkt (s);
        !           779:                return DONE;
        !           780: 
        !           781:            case SPDU_MIP:
        !           782:                if (!(sb -> sb_flags & SB_Vsc)) {
        !           783:                    sb -> sb_V_A = sb -> sb_V_M;
        !           784:                    sb -> sb_flags |= SB_Vsc;
        !           785:                }
        !           786:                sb -> sb_V_M++;
        !           787:                if (sb -> sb_flags & (SB_ED | SB_ERACK)) {
        !           788:                    freespkt (s);
        !           789:                    goto spin;
        !           790:                }
        !           791:                si -> si_type = SI_SYNC;
        !           792:                {
        !           793:                    register struct SSAPsync *sn = &si -> si_sync;
        !           794: 
        !           795:                    sn -> sn_type = SN_MINORIND;
        !           796:                    sn -> sn_options = (s -> s_mask & SMASK_MIP_SYNC)
        !           797:                            && (s -> s_mip_sync & MIP_SYNC_NOEXPL)
        !           798:                            ? SYNC_NOCONFIRM : SYNC_CONFIRM;
        !           799:                    sn -> sn_ssn = s -> s_mip_serial;
        !           800:                    copySPKTdata (s, sn);
        !           801:                }
        !           802:                freespkt (s);
        !           803:                return DONE;
        !           804: 
        !           805:            case SPDU_MIA:
        !           806:                if ((sb -> sb_flags & SB_Vsc)
        !           807:                        || sb -> sb_V_A > s -> s_mia_serial
        !           808:                        || s -> s_mia_serial >= sb -> sb_V_M) {
        !           809:                    freespkt (s);
        !           810:                    goto spin;
        !           811:                }
        !           812:                sb -> sb_V_A = s -> s_mia_serial;
        !           813:                si -> si_type = SI_SYNC;
        !           814:                {
        !           815:                    register struct SSAPsync *sn = &si -> si_sync;
        !           816: 
        !           817:                    sn -> sn_type = SN_MINORCNF;
        !           818:                    sn -> sn_ssn = s -> s_mia_serial;
        !           819:                    copySPKTdata (s, sn);
        !           820:                }
        !           821:                freespkt (s);
        !           822:                return DONE;
        !           823: 
        !           824:            case SPDU_RS:
        !           825:                if (s -> s_rs_type == SYNC_RESTART
        !           826:                        && sb -> sb_V_R > s -> s_rs_serial) {
        !           827:                    freespkt (s);
        !           828:                    goto spin;
        !           829:                }
        !           830:                sb -> sb_flags &= ~SB_RS, sb -> sb_flags |= SB_RA;
        !           831:                sb -> sb_rs = s -> s_rs_type;
        !           832:                sb -> sb_rsn = s -> s_rs_serial;
        !           833:                if (s -> s_mask & SMASK_RS_SET)
        !           834:                    sb -> sb_rsettings = s -> s_rs_settings;
        !           835:                else {
        !           836:                    sb -> sb_rsettings = 0;
        !           837: #define        dotoken(requires,shift,bit,type) \
        !           838: { \
        !           839:                    if (sb -> sb_requirements & requires) \
        !           840:                        if ((sb -> sb_owned & bit) \
        !           841:                                && (sb -> sb_flags & SB_INIT)) \
        !           842:                            sb -> sb_rsettings = ST_INIT_VALUE << shift; \
        !           843:                        else \
        !           844:                            sb -> sb_rsettings = ST_RESP_VALUE << shift; \
        !           845: }
        !           846:                    dotokens ();
        !           847: #undef dotoken
        !           848:                }
        !           849:                si -> si_type = SI_SYNC;
        !           850:                {
        !           851:                    register struct SSAPsync *sn = &si -> si_sync;
        !           852: 
        !           853:                    sn -> sn_type = SN_RESETIND;
        !           854:                    sn -> sn_options = sb -> sb_rs;
        !           855:                    sn -> sn_ssn = sb -> sb_rsn;
        !           856:                    sn -> sn_settings = sb -> sb_rsettings;
        !           857:                    copySPKTdata (s, sn);
        !           858:                }
        !           859:                freespkt (s);
        !           860:                return DONE;
        !           861: 
        !           862:            case SPDU_RA:
        !           863:                sb -> sb_flags &= ~SB_RS;
        !           864:                sb -> sb_V_A = sb -> sb_V_M = s -> s_ra_serial;
        !           865:                if (sb -> sb_rs != SYNC_RESTART)
        !           866:                    sb -> sb_V_R = 0;
        !           867:                if (s -> s_mask & SMASK_RA_SET)
        !           868:                    sb -> sb_rsettings = s -> s_ra_settings;
        !           869: #define        dotoken(requires,shift,bit,type) \
        !           870: { \
        !           871:                if (sb -> sb_requirements & requires) \
        !           872:                    switch (sb -> sb_rsettings & (ST_MASK << shift)) { \
        !           873:                        dotoken1 (requires,shift,bit,type); \
        !           874:  \
        !           875:                        dotoken2 (requires,shift,bit,type); \
        !           876:                    } \
        !           877: }
        !           878: #define        dotoken1(requires,shift,bit,type) \
        !           879:                        case ST_CALL_VALUE << shift: \
        !           880:                            switch (s -> s_ra_settings & (ST_MASK << shift)) { \
        !           881:                                case ST_INIT_VALUE: \
        !           882:                                    if (sb -> sb_flags & SB_INIT) \
        !           883:                                        sb -> sb_owned |= bit; \
        !           884:                                    else \
        !           885:                                        sb -> sb_owned &= ~bit; \
        !           886:                                    break; \
        !           887:  \
        !           888:                                case ST_RESP_VALUE: \
        !           889:                                    if (!(sb -> sb_flags & SB_INIT)) \
        !           890:                                        sb -> sb_owned |= bit; \
        !           891:                                    else \
        !           892:                                        sb -> sb_owned &= ~bit; \
        !           893:                                    break; \
        !           894:                            } \
        !           895:                            break;
        !           896: #define        dotoken2(requires,shift,bit,type) \
        !           897:                        case ST_INIT_VALUE << shift: \
        !           898:                            if (sb -> sb_flags & SB_INIT) \
        !           899:                                sb -> sb_owned |= bit; \
        !           900:                            else \
        !           901:                                sb -> sb_owned &= ~bit; \
        !           902:                            break; \
        !           903:  \
        !           904:                        case ST_RESP_VALUE << shift: \
        !           905:                            if (!(sb -> sb_flags & SB_INIT)) \
        !           906:                                sb -> sb_owned |= bit; \
        !           907:                            else \
        !           908:                                sb -> sb_owned &= ~bit; \
        !           909:                            break;
        !           910:                dotokens ();
        !           911: #undef dotoken
        !           912: #undef dotoken1
        !           913: #undef dotoken2
        !           914:                si -> si_type = SI_SYNC;
        !           915:                {
        !           916:                    register struct SSAPsync *sn = &si -> si_sync;
        !           917: 
        !           918:                    sn -> sn_type = SN_RESETCNF;
        !           919:                    sn -> sn_ssn = sb -> sb_V_M;
        !           920:                    sn -> sn_settings = sb -> sb_rsettings;
        !           921:                    copySPKTdata (s, sn);
        !           922:                }
        !           923:                freespkt (s);
        !           924:                return DONE;
        !           925: 
        !           926:            case SPDU_PR: 
        !           927:                switch (s -> s_pr_type) {
        !           928:                    case PR_MAA: 
        !           929:                        sb -> sb_pr = SPDU_MAA;
        !           930:                        break;
        !           931:                    case PR_RS: 
        !           932:                        sb -> sb_flags &= ~(SB_ED | SB_ERACK);
        !           933:                        sb -> sb_pr = SPDU_RS;
        !           934:                        break;
        !           935:                    case PR_RA: 
        !           936:                        sb -> sb_pr = SPDU_RA;
        !           937:                        break;
        !           938:                    case PR_AB: 
        !           939:                        sb -> sb_pr = SPDU_AB;
        !           940:                        break;
        !           941:                }
        !           942:                freespkt (s);
        !           943:                goto spin;
        !           944: 
        !           945:            case SPDU_ER:       /* this implementation never generates these */
        !           946:                sb -> sb_flags |= SB_ERACK;
        !           947:                si -> si_type = SI_REPORT;
        !           948:                {
        !           949:                    register struct SSAPreport *sp = &si -> si_report;
        !           950: 
        !           951:                    sp -> sp_peer = 0;
        !           952:                    sp -> sp_reason = SP_PROTOCOL;
        !           953:                }
        !           954:                freespkt (s);
        !           955:                return DONE;
        !           956: 
        !           957:            case SPDU_ED:
        !           958:                if (sb -> sb_owned & ST_DAT_TOKEN)
        !           959:                    sb -> sb_flags |= SB_EDACK;
        !           960:                si -> si_type = SI_REPORT;
        !           961:                {
        !           962:                    register struct SSAPreport *sp = &si -> si_report;
        !           963: 
        !           964:                    sp -> sp_peer = 1;
        !           965:                    sp -> sp_reason = s -> s_ed_reason;
        !           966:                    copySPKTdata (s, sp);
        !           967:                }
        !           968:                freespkt (s);
        !           969:                return DONE;
        !           970: 
        !           971:            case SPDU_AS:
        !           972:                if (sb -> sb_flags & SB_Vact) {
        !           973:                    freespkt (s);
        !           974:                    goto spin;
        !           975:                }
        !           976:                sb -> sb_V_A = sb -> sb_V_M = sb -> sb_V_R = 1;
        !           977:                sb -> sb_flags |= SB_Vact;
        !           978:                si -> si_type = SI_ACTIVITY;
        !           979:                {
        !           980:                    register struct SSAPactivity *sv = &si -> si_activity;
        !           981: 
        !           982:                    sv -> sv_type = SV_START;
        !           983:                    sv -> sv_id = s -> s_as_id; /* struct copy */
        !           984:                    copySPKTdata (s, sv);
        !           985:                }
        !           986:                freespkt (s);
        !           987:                return DONE;
        !           988: 
        !           989:            case SPDU_AR:
        !           990:                if (sb -> sb_flags & SB_Vact) {
        !           991:                    freespkt (s);
        !           992:                    goto spin;
        !           993:                }
        !           994:                sb -> sb_V_A = sb -> sb_V_M = s -> s_ar_serial + 1;
        !           995:                sb -> sb_V_R = 1;
        !           996:                sb -> sb_flags |= SB_Vact;
        !           997:                si -> si_type = SI_ACTIVITY;
        !           998:                {
        !           999:                    register struct SSAPactivity *sv = &si -> si_activity;
        !          1000: 
        !          1001:                    sv -> sv_type = SV_RESUME;
        !          1002:                    sv -> sv_id = s -> s_ar_id; /* struct copy */
        !          1003:                    sv -> sv_oid = s -> s_ar_oid;       /* struct copy */
        !          1004:                    if (s -> s_mask & SMASK_AR_REF)     /* struct copy */
        !          1005:                        sv -> sv_connect = s -> s_ar_reference;
        !          1006:                    sv -> sv_ssn = s -> s_ar_serial;
        !          1007:                    copySPKTdata (s, sv);
        !          1008:                }
        !          1009:                freespkt (s);
        !          1010:                return DONE;
        !          1011: 
        !          1012:            case SPDU_AD:
        !          1013: spdu_ai: ;
        !          1014:                if (!(sb -> sb_flags & SB_Vact)) {
        !          1015:                    freespkt (s);
        !          1016:                    goto spin;
        !          1017:                }
        !          1018:                sb -> sb_flags &= ~(SB_RS | SB_RA), sb -> sb_flags |= SB_AIA;
        !          1019:                sb -> sb_rs = SYNC_INTR;
        !          1020:                si -> si_type = SI_ACTIVITY;
        !          1021:                {
        !          1022:                    register struct SSAPactivity *sv = &si -> si_activity;
        !          1023: 
        !          1024:                    sv -> sv_type = s -> s_code == SPDU_AI ? SV_INTRIND
        !          1025:                            : SV_DISCIND;
        !          1026:                    sv -> sv_reason = s -> s_ai_reason;
        !          1027:                }
        !          1028:                freespkt (s);
        !          1029:                return DONE;
        !          1030: 
        !          1031:            case SPDU_AA:
        !          1032: #ifdef notdef
        !          1033:            case SPDU_AIA:      /* aka SPDU_AA */
        !          1034: #endif
        !          1035:                if (s -> s_mask & SMASK_SPDU_AA) {
        !          1036:                    freespkt (s);
        !          1037:                    goto spin;
        !          1038:                }               /* else fall */
        !          1039:            case SPDU_ADA:
        !          1040:                if (!(sb -> sb_flags & SB_Vact)) {
        !          1041:                    freespkt (s);
        !          1042:                    goto spin;
        !          1043:                }
        !          1044:                sb -> sb_flags &= ~(SB_AI | SB_Vact);
        !          1045: #define        dotoken(requires,shift,bit,type) \
        !          1046: { \
        !          1047:                if (sb -> sb_requirements & requires) \
        !          1048:                    sb -> sb_owned |= bit; \
        !          1049: }
        !          1050:                dotokens ();
        !          1051: #undef dotoken
        !          1052:                si -> si_type = SI_ACTIVITY;
        !          1053:                {
        !          1054:                    register struct SSAPactivity *sv = &si -> si_activity;
        !          1055: 
        !          1056:                    sv -> sv_type = s -> s_code == SPDU_AIA ? SV_INTRCNF
        !          1057:                                        : SV_DISCCNF;
        !          1058:                }
        !          1059:                freespkt (s);
        !          1060:                return DONE;            
        !          1061: 
        !          1062: spdu_ae: ;
        !          1063:                if (!(sb -> sb_flags & SB_Vsc))
        !          1064:                    sb -> sb_V_A = sb -> sb_V_M;
        !          1065:                sb -> sb_V_M++;
        !          1066:                sb -> sb_flags &= ~SB_Vnextact;
        !          1067:                sb -> sb_flags |= SB_MAA | SB_AE;
        !          1068:                si -> si_type = SI_ACTIVITY;
        !          1069:                {
        !          1070:                    register struct SSAPactivity *sv = &si -> si_activity;
        !          1071: 
        !          1072:                    sv -> sv_type = SV_ENDIND;
        !          1073:                    sv -> sv_ssn = s -> s_map_serial;
        !          1074:                    copySPKTdata (s, sv);
        !          1075:                }
        !          1076:                freespkt (s);
        !          1077:                return DONE;
        !          1078: 
        !          1079:            case SPDU_FN: 
        !          1080:                sb -> sb_flags |= SB_FINN;
        !          1081:                si -> si_type = SI_FINISH;
        !          1082:                {
        !          1083:                    register struct SSAPfinish *sf = &si -> si_finish;
        !          1084: 
        !          1085:                    copySPKTdata (s, sf);
        !          1086:                }
        !          1087:                freespkt (s);
        !          1088:                return DONE;
        !          1089: 
        !          1090:            case SPDU_AB: 
        !          1091:                if (!(s -> s_mask & SMASK_SPDU_AB))
        !          1092:                    goto spdu_ai;
        !          1093:                sb -> sb_flags &= ~(SB_ED | SB_EDACK | SB_ERACK);
        !          1094:                si -> si_type = SI_ABORT;
        !          1095:                {
        !          1096:                    register struct SSAPabort  *sa = &si -> si_abort;
        !          1097: 
        !          1098:                    if (!(sa -> sa_peer = (s -> s_ab_disconnect & AB_DISC_USER)
        !          1099:                                ? 1 : 0))
        !          1100:                        sa -> sa_reason = SC_ABORT;
        !          1101:                    sa -> sa_info = s -> s_udata, sa -> sa_cc = s -> s_ulen;
        !          1102:                    sa -> sa_realinfo = s -> s_udata, s -> s_udata = NULL;
        !          1103:                }
        !          1104: #ifdef notdef          /* only if transport connection is to be re-used */
        !          1105:                freespkt (s);
        !          1106:                if (s = newspkt (SPDU_AA)) {
        !          1107:                    s -> s_mask |= SMASK_SPDU_AA;
        !          1108:                    (void) spkt2sd (s, sb -> sb_fd, sb -> sb_flags & SB_EXPD
        !          1109:                                ? 1 : 0, (struct SSAPindication *) 0);
        !          1110:                }
        !          1111: #endif
        !          1112:                break;
        !          1113: 
        !          1114:            default: 
        !          1115:                (void) spktlose (sb -> sb_fd, si, SC_PROTOCOL, NULLCP,
        !          1116:                        "session protocol mangled: not expecting 0x%x",
        !          1117:                        s -> s_code);
        !          1118:                break;
        !          1119:        }
        !          1120:        break;
        !          1121:     }
        !          1122: 
        !          1123:     if (si -> si_abort.sa_reason == SC_TIMER)
        !          1124:        return NOTOK;
        !          1125: 
        !          1126: out: ;
        !          1127:     freespkt (s);
        !          1128:     freesblk (sb);
        !          1129: 
        !          1130:     return NOTOK;
        !          1131: }
        !          1132: 
        !          1133: /*  */
        !          1134: 
        !          1135: /* a decision tree (ugh!) */
        !          1136: 
        !          1137: int    SDoCollideAux (init, localop, localssn, remoteop, remotessn)
        !          1138: int     init,
        !          1139:        localop,
        !          1140:         remoteop;
        !          1141: long    localssn,
        !          1142:         remotessn;
        !          1143: {
        !          1144:     SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !          1145:          ("collide: local<%d,%ld,%s> remote<%d,%ld,%s>",
        !          1146:           localop, localssn, init ? "initiator" : "responder",
        !          1147:           remoteop, remotessn, init ? "responder" : "initiator"));
        !          1148: 
        !          1149:     if (localop == SYNC_DISC)
        !          1150:        return OK;
        !          1151: 
        !          1152:     if (remoteop == SYNC_DISC)
        !          1153:        return NOTOK;
        !          1154: 
        !          1155:     if (localop == SYNC_INTR)
        !          1156:        return OK;
        !          1157: 
        !          1158:     if (remoteop == SYNC_DISC)
        !          1159:        return NOTOK;
        !          1160: 
        !          1161:     if (localop == SYNC_ABANDON) {
        !          1162:        if (remoteop != SYNC_ABANDON)
        !          1163:            return OK;
        !          1164: 
        !          1165:        return (init ? OK : NOTOK);
        !          1166:     }
        !          1167:     else
        !          1168:        if (remoteop == SYNC_ABANDON)
        !          1169:            return NOTOK;
        !          1170: 
        !          1171:     if (localop == SYNC_SET) {
        !          1172:        if (remoteop != SYNC_SET)
        !          1173:            return OK;
        !          1174: 
        !          1175:        return (init ? OK : NOTOK);
        !          1176:     }
        !          1177:     else
        !          1178:        if (remoteop == SYNC_SET)
        !          1179:            return NOTOK;
        !          1180: 
        !          1181:     if (localssn == remotessn)
        !          1182:        return (init ? OK : NOTOK);
        !          1183: 
        !          1184:     return (localssn < remotessn ? OK : NOTOK);
        !          1185: }
        !          1186: 
        !          1187: /*    define vectors for INDICATION events */
        !          1188: 
        !          1189: int    SSetIndications (sd, data, tokens, sync, activity, report, finish,
        !          1190:                abort, si)
        !          1191: int    sd;
        !          1192: IFP    data,   
        !          1193:        tokens,
        !          1194:        sync,
        !          1195:        activity,
        !          1196:        report,
        !          1197:        finish,
        !          1198:        abort;
        !          1199: struct SSAPindication *si;
        !          1200: {
        !          1201:     SBV     smask;
        !          1202:     register struct ssapblk *sb;
        !          1203:     struct TSAPdisconnect   tds;
        !          1204:     register struct TSAPdisconnect *td = &tds;
        !          1205: 
        !          1206:     if (data || tokens || sync || activity || report || finish || abort) {
        !          1207:        missingP (data);
        !          1208:        missingP (tokens);
        !          1209:        missingP (sync);
        !          1210:        missingP (activity);
        !          1211:        missingP (report);
        !          1212:        missingP (finish);
        !          1213:        missingP (abort);
        !          1214:     }
        !          1215: 
        !          1216:     smask = sigioblock ();
        !          1217: 
        !          1218:     ssapPsig (sb, sd);
        !          1219: 
        !          1220:     if (TSetIndications (sb -> sb_fd, TDATAser, TDISCser, td) == NOTOK)
        !          1221:        if (td -> td_reason == DR_WAITING)
        !          1222:            return ssaplose (si, SC_WAITING, NULLCP, NULLCP);
        !          1223:        else
        !          1224:            return ts2sslose (si, "TSetIndications", td);
        !          1225: 
        !          1226:     if (sb -> sb_DataIndication = data)
        !          1227:        sb -> sb_flags |= SB_ASYN;
        !          1228:     else
        !          1229:        sb -> sb_flags &= ~SB_ASYN;
        !          1230:     sb -> sb_TokenIndication = tokens;
        !          1231:     sb -> sb_SyncIndication = sync;
        !          1232:     sb -> sb_ActivityIndication = activity;
        !          1233:     sb -> sb_ReportIndication = report;
        !          1234:     sb -> sb_ReleaseIndication = finish;
        !          1235:     sb -> sb_AbortIndication = abort;
        !          1236: 
        !          1237:     (void) sigiomask (smask);
        !          1238: 
        !          1239:     return OK;
        !          1240: }
        !          1241: 
        !          1242: /*    TSAP interface */
        !          1243: 
        !          1244: int    spkt2sd (s, sd, expedited, si)
        !          1245: register struct ssapkt *s;
        !          1246: int     sd,
        !          1247:         expedited;
        !          1248: register struct SSAPindication *si;
        !          1249: {
        !          1250:     int     i,
        !          1251:             len,
        !          1252:             result;
        !          1253:     char   *base,
        !          1254:            *dp;
        !          1255:     struct TSAPdisconnect   tds;
        !          1256:     register struct TSAPdisconnect *td = &tds;
        !          1257: 
        !          1258:     if (expedited)
        !          1259:        s -> s_mask |= SMASK_SPDU_EXPD;
        !          1260:     if (spkt2tsdu (s, &base, &len) == NOTOK) {
        !          1261:        (void) ssaplose (si, s -> s_errno, NULLCP, NULLCP);
        !          1262:        return NOTOK;
        !          1263:     }
        !          1264:     if (s -> s_code == SPDU_EX) {/* only SX_EXSIZE octets, so no big deal... */
        !          1265:        if (s -> s_udata) {
        !          1266:            if ((dp = realloc (base, (unsigned) (i = len + s -> s_ulen)))
        !          1267:                    == NULL) {
        !          1268:                free (base);
        !          1269:                (void) ssaplose (si, SC_CONGEST, NULLCP, NULLCP);
        !          1270:                return NOTOK;
        !          1271:            }
        !          1272:            bcopy (s -> s_udata, (base = dp) + len, s -> s_ulen);
        !          1273:            len = i;
        !          1274:        }
        !          1275:     }
        !          1276: 
        !          1277:     if (len > TX_SIZE)
        !          1278:        expedited = 0;
        !          1279:     if ((result = expedited ? TExpdRequest (sd, base, len, td)
        !          1280:                : TDataRequest (sd, base, len, td)) == NOTOK)
        !          1281:        (void) ts2sslose (si, expedited ? "TExpdRequest" : "TDataRequest", td);
        !          1282: 
        !          1283:     if (base)
        !          1284:        free (base);
        !          1285: 
        !          1286:     return result;
        !          1287: }
        !          1288: 
        !          1289: /*  */
        !          1290: 
        !          1291: struct ssapkt   *sb2spkt (sb, si, secs, ty)
        !          1292: register struct ssapblk *sb;
        !          1293: register struct SSAPindication *si;
        !          1294: int     secs;
        !          1295: register struct TSAPdata   *ty;
        !          1296: {
        !          1297:     int     cc;
        !          1298:     register struct ssapkt   *s,
        !          1299:                             *p;
        !          1300:     struct TSAPdata txs;
        !          1301:     register struct TSAPdata   *tx = &txs;
        !          1302:     struct TSAPdisconnect   tds;
        !          1303:     register struct TSAPdisconnect *td = &tds;
        !          1304: 
        !          1305:     if (sb -> sb_pr == SPDU_PR && sb -> sb_xspdu) {
        !          1306:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !          1307:              ("returning XSDU buffered during preparation"));
        !          1308:        s = sb -> sb_xspdu;
        !          1309:        sb -> sb_xspdu = NULL;
        !          1310: 
        !          1311:        return s;
        !          1312:     }
        !          1313: 
        !          1314:     if (sb -> sb_spdu) {       /* get previous category 0 SPDU */
        !          1315:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !          1316:              ("returning category 0 SPDU previously buffered"));
        !          1317:        s = sb -> sb_spdu;
        !          1318:        sb -> sb_spdu = NULL;
        !          1319: 
        !          1320:        return s;
        !          1321:     }
        !          1322: 
        !          1323:     if (ty) {
        !          1324:        *tx = *ty;              /* struct copy */
        !          1325:        tx -> tx_qbuf.qb_forw -> qb_back =
        !          1326:                tx -> tx_qbuf.qb_back -> qb_forw = &tx -> tx_qbuf;
        !          1327:        bzero ((char *) ty, sizeof *ty);
        !          1328:        ty -> tx_qbuf.qb_forw = ty -> tx_qbuf.qb_back = &ty -> tx_qbuf;
        !          1329:     }
        !          1330:     else
        !          1331:        if (TReadRequest (sb -> sb_fd, tx, secs, td) == NOTOK) {
        !          1332:            if (td -> td_reason != DR_TIMER)
        !          1333:                (void) ts2sslose (si, "TReadRequest", td);
        !          1334:            else
        !          1335:                (void) ssaplose (si, SC_TIMER, NULLCP, NULLCP);
        !          1336: 
        !          1337:            return NULL;
        !          1338:        }
        !          1339: 
        !          1340:     DLOG (ssap_log, LLOG_DEBUG, ("read TSDU, size %d", tx -> tx_cc));
        !          1341: 
        !          1342:     if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 1, &cc))) == NULL
        !          1343:            || s -> s_errno != SC_ACCEPT) {
        !          1344:        (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
        !          1345: bad1: ;
        !          1346:        freespkt (s);
        !          1347:        TXFREE (tx);
        !          1348:        return NULL;
        !          1349:     }
        !          1350: 
        !          1351:     if (tx -> tx_expedited)
        !          1352:        s -> s_mask |= SMASK_SPDU_EXPD;
        !          1353:     tx -> tx_cc -= cc;
        !          1354: 
        !          1355:     switch (s -> s_code) {
        !          1356:        case SPDU_GT:           /* category 0 SPDUs */
        !          1357:        case SPDU_PT: 
        !          1358:            if (tx -> tx_cc <= 0)
        !          1359:                goto simple;
        !          1360:            break;
        !          1361: 
        !          1362:        case SPDU_EX:           /* category 1 SPDUs with user data */
        !          1363:        case SPDU_TD: 
        !          1364:            if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
        !          1365:                s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
        !          1366:                s -> s_qbuf.qb_forw -> qb_back =
        !          1367:                        s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
        !          1368:                s -> s_qlen = tx -> tx_cc;
        !          1369:            }
        !          1370:            return s;
        !          1371: 
        !          1372:        case SPDU_CN:           /* category 1 SPDUs */
        !          1373:        case SPDU_AC: 
        !          1374:        case SPDU_RF: 
        !          1375:        case SPDU_FN: 
        !          1376:        case SPDU_DN: 
        !          1377:        case SPDU_NF: 
        !          1378:        case SPDU_AB: 
        !          1379:        case SPDU_AA: 
        !          1380:        case SPDU_GTC: 
        !          1381:        case SPDU_GTA: 
        !          1382:        case SPDU_PR: 
        !          1383:            if (tx -> tx_cc <= 0) {
        !          1384:        simple: ;
        !          1385:                TXFREE (tx);
        !          1386:                return s;
        !          1387:            }
        !          1388:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
        !          1389:                    "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
        !          1390:                    s -> s_code, tx -> tx_cc);
        !          1391:            goto bad1;
        !          1392: 
        !          1393:        default:
        !          1394:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
        !          1395:                    "session protocol mangled: not expecting 0x%x",
        !          1396:                    s -> s_code);
        !          1397:            goto bad1;
        !          1398:     }
        !          1399: 
        !          1400:     sb -> sb_spdu = p = s;             /* save category 0 SPDU */
        !          1401: 
        !          1402:     if ((s = tsdu2spkt (&tx -> tx_qbuf, tx -> tx_cc, (cc = 0, &cc))) == NULL
        !          1403:            || s -> s_errno != SC_ACCEPT) {
        !          1404:        (void) ssaplose (si, s ? s -> s_errno : SC_CONGEST, NULLCP, NULLCP);
        !          1405: bad2:  ;
        !          1406:        freespkt (s);
        !          1407:        freespkt (p);
        !          1408:        sb -> sb_spdu = NULL;
        !          1409:        TXFREE (tx);
        !          1410:        return NULL;
        !          1411:     }
        !          1412: 
        !          1413:     if (tx -> tx_expedited)
        !          1414:        s -> s_mask |= SMASK_SPDU_EXPD;
        !          1415:     tx -> tx_cc -= cc;
        !          1416: 
        !          1417:     switch ((p -> s_code) << 8 | s -> s_code) {
        !          1418:        case (SPDU_GT << 8) | SPDU_DT:  /* category 2 SPDUs with user data */
        !          1419:            if (tx -> tx_qbuf.qb_forw != &tx -> tx_qbuf) {
        !          1420:                s -> s_qbuf = tx -> tx_qbuf;/* struct copy */
        !          1421:                s -> s_qbuf.qb_forw -> qb_back =
        !          1422:                        s -> s_qbuf.qb_back -> qb_forw = &s -> s_qbuf;
        !          1423:                s -> s_qlen = tx -> tx_cc;
        !          1424:            }
        !          1425:            break;
        !          1426: 
        !          1427:        case (SPDU_GT << 8) | SPDU_MIP: /* category 2 SPDUs */
        !          1428:        case (SPDU_PT << 8) | SPDU_MIA: 
        !          1429:        case (SPDU_GT << 8) | SPDU_MAP: 
        !          1430:        case (SPDU_PT << 8) | SPDU_MAA: 
        !          1431:        case (SPDU_GT << 8) | SPDU_RS: 
        !          1432:        case (SPDU_PT << 8) | SPDU_RA: 
        !          1433:        case (SPDU_GT << 8) | SPDU_AS: 
        !          1434:        case (SPDU_GT << 8) | SPDU_AR: 
        !          1435:        case (SPDU_GT << 8) | SPDU_AD: 
        !          1436:        case (SPDU_PT << 8) | SPDU_ADA: 
        !          1437:        case (SPDU_GT << 8) | SPDU_AI:
        !          1438:        case (SPDU_PT << 8) | SPDU_AIA: 
        !          1439: #ifdef notdef
        !          1440:        case (SPDU_GT << 8) | SPDU_AE:  /* aka SPDU_MAP */
        !          1441:        case (SPDU_PT << 8) | SPDU_AEA: /* aka SPDU_MAA */
        !          1442: #endif
        !          1443:        case (SPDU_GT << 8) | SPDU_CD: 
        !          1444:        case (SPDU_PT << 8) | SPDU_CDA: 
        !          1445:        case (SPDU_PT << 8) | SPDU_ER: 
        !          1446:        case (SPDU_PT << 8) | SPDU_ED: 
        !          1447:            if (tx -> tx_cc <= 0) {
        !          1448:                TXFREE (tx);
        !          1449:                break;
        !          1450:            }
        !          1451:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
        !          1452:                    "session protocol mangled: not expecting user information after 0x%x (%d bytes)",
        !          1453:                    s -> s_code, tx -> tx_cc);
        !          1454:                goto bad2;
        !          1455: 
        !          1456:        default: 
        !          1457:            (void) ssaplose (si, SC_PROTOCOL, NULLCP,
        !          1458:                    "session protocol mangled: not expecting 0x%x to be concatenated after 0x%x",
        !          1459:                    s -> s_code, p -> s_code);
        !          1460:            goto bad2;
        !          1461:     }
        !          1462: 
        !          1463:     switch (s -> s_code) {
        !          1464:        default:
        !          1465:            if (p -> s_code == SPDU_GT) {
        !          1466:                if ((p -> s_mask & SMASK_GT_TOKEN) && p -> s_gt_token)
        !          1467:                    break;
        !          1468:            }
        !          1469:            else {
        !          1470:                if (((p -> s_mask & SMASK_PT_TOKEN) && p -> s_pt_token)
        !          1471:                        || p -> s_ulen)
        !          1472:                    break;
        !          1473:            }                   /* fall... */
        !          1474: 
        !          1475:        case SPDU_RS: 
        !          1476:        case SPDU_AD: 
        !          1477:        case SPDU_AI: 
        !          1478:        case SPDU_CD: 
        !          1479:            freespkt (p);
        !          1480:            sb -> sb_spdu = NULL;
        !          1481:            break;
        !          1482:     }
        !          1483: 
        !          1484:     return s;
        !          1485: }
        !          1486: 
        !          1487: /*  */
        !          1488: 
        !          1489: static int  TDATAser (sd, tx)
        !          1490: int     sd;
        !          1491: register struct TSAPdata   *tx;
        !          1492: {
        !          1493:     IFP            abort;
        !          1494:     register struct ssapblk *sb;
        !          1495:     struct SSAPdata sxs;
        !          1496:     register struct SSAPdata   *sx = &sxs;
        !          1497:     struct SSAPindication   sis;
        !          1498:     register struct SSAPindication *si = &sis;
        !          1499:     register struct SSAPabort  *sa = &si -> si_abort;
        !          1500: 
        !          1501:     if ((sb = findsblk (sd)) == NULL)
        !          1502:        return;
        !          1503: 
        !          1504:     abort = sb -> sb_AbortIndication;
        !          1505: 
        !          1506:     for (;; tx = NULLTX) {
        !          1507:        switch (SReadRequestAux (sb, sx, OK, si, 1, tx)) {
        !          1508:            case NOTOK: 
        !          1509:                (*abort) (sd, sa);
        !          1510:                return;
        !          1511: 
        !          1512:            case OK: 
        !          1513:                (*sb -> sb_DataIndication) (sd, sx);
        !          1514:                break;
        !          1515: 
        !          1516:            case DONE: 
        !          1517:                switch (si -> si_type) {
        !          1518:                    case SI_TOKEN: 
        !          1519:                        (*sb -> sb_TokenIndication) (sd, &si -> si_token);
        !          1520:                        break;
        !          1521: 
        !          1522:                    case SI_SYNC: 
        !          1523:                        (*sb -> sb_SyncIndication) (sd, &si -> si_sync);
        !          1524:                        break;
        !          1525: 
        !          1526:                    case SI_ACTIVITY: 
        !          1527:                        (*sb -> sb_ActivityIndication) (sd, &si -> si_activity);
        !          1528:                        break;
        !          1529: 
        !          1530:                    case SI_REPORT: 
        !          1531:                        (*sb -> sb_ReportIndication) (sd, &si -> si_report);
        !          1532:                        break;
        !          1533: 
        !          1534:                    case SI_FINISH: 
        !          1535:                        (*sb -> sb_ReleaseIndication) (sd, &si -> si_finish);
        !          1536:                        break;
        !          1537: 
        !          1538:                    case SI_DATA: /* partially assembled (T)SSDU */
        !          1539:                        break;
        !          1540:                }
        !          1541:                break;
        !          1542:        }
        !          1543: 
        !          1544:        if (sb -> sb_spdu == NULL)
        !          1545:            break;
        !          1546:     }
        !          1547: }
        !          1548: 
        !          1549: /*  */
        !          1550: 
        !          1551: static int TDISCser (sd, td)
        !          1552: int    sd;
        !          1553: register struct TSAPdisconnect *td;
        !          1554: {
        !          1555:     IFP            abort;
        !          1556:     register struct ssapblk *sb;
        !          1557:     struct SSAPindication sis;
        !          1558:     register struct SSAPindication *si = &sis;
        !          1559: 
        !          1560:     if ((sb = findsblk (sd)) == NULL)
        !          1561:        return;
        !          1562: 
        !          1563:     (void) ts2sslose (si, NULLCP, td);
        !          1564: 
        !          1565:     abort = sb -> sb_AbortIndication;
        !          1566: 
        !          1567:     sb -> sb_fd = NOTOK;
        !          1568:     (void) freesblk (sb);
        !          1569: 
        !          1570:     (*abort) (sd, &si -> si_abort);
        !          1571: }
        !          1572: 
        !          1573: /*  */
        !          1574: 
        !          1575: int    ts2sslose (si, event, td)
        !          1576: register struct SSAPindication *si;
        !          1577: char   *event;
        !          1578: register struct TSAPdisconnect *td;
        !          1579: {
        !          1580:     int     reason;
        !          1581:     char   *cp,
        !          1582:             buffer[BUFSIZ];
        !          1583: 
        !          1584:     if (event)
        !          1585:        SLOG (ssap_log, LLOG_EXCEPTIONS, NULLCP,
        !          1586:              (td -> td_cc > 0 ? "%s: %s [%*.*s]": "%s: %s", event,
        !          1587:               TErrString (td -> td_reason), td -> td_cc, td -> td_cc,
        !          1588:               td -> td_data));
        !          1589: 
        !          1590:     cp = "";
        !          1591:     switch (td -> td_reason) {
        !          1592:        case DR_REMOTE: 
        !          1593:        case DR_CONGEST: 
        !          1594:            reason = SC_CONGEST;
        !          1595:            break;
        !          1596: 
        !          1597:        case DR_SESSION: 
        !          1598:        case DR_ADDRESS: 
        !          1599:            reason = SC_ADDRESS;
        !          1600:            break;
        !          1601: 
        !          1602:        case DR_REFUSED:
        !          1603:            reason = SC_REFUSED;
        !          1604:            break;
        !          1605: 
        !          1606:        default: 
        !          1607:            (void) sprintf (cp = buffer, " (%s at transport)",
        !          1608:                    TErrString (td -> td_reason));
        !          1609:        case DR_NETWORK:
        !          1610:            reason = SC_TRANSPORT;
        !          1611:            break;
        !          1612:     }
        !          1613: 
        !          1614:     if (td -> td_cc > 0)
        !          1615:        return ssaplose (si, reason, NULLCP, "%*.*s%s",
        !          1616:                td -> td_cc, td -> td_cc, td -> td_data, cp);
        !          1617:     else
        !          1618:        return ssaplose (si, reason, NULLCP, "%s", *cp ? cp + 1 : cp);
        !          1619: }
        !          1620: 
        !          1621: /*    INTERNAL */
        !          1622: 
        !          1623: struct ssapblk  *newsblk () {
        !          1624:     register struct ssapblk *sb;
        !          1625: 
        !          1626:     sb = (struct ssapblk   *) calloc (1, sizeof *sb);
        !          1627:     if (sb == NULL)
        !          1628:        return NULL;
        !          1629: 
        !          1630:     sb -> sb_fd = NOTOK;
        !          1631:     sb -> sb_qbuf.qb_forw = sb -> sb_qbuf.qb_back = &sb -> sb_qbuf;
        !          1632:     sb -> sb_pr = SPDU_PR;
        !          1633: 
        !          1634:     if (once_only == 0) {
        !          1635:        SHead -> sb_forw = SHead -> sb_back = SHead;
        !          1636:        once_only++;
        !          1637:     }
        !          1638: 
        !          1639:     insque (sb, SHead -> sb_back);
        !          1640: 
        !          1641:     return sb;
        !          1642: }
        !          1643: 
        !          1644: 
        !          1645: int    freesblk (sb)
        !          1646: register struct ssapblk *sb;
        !          1647: {
        !          1648:     if (sb == NULL)
        !          1649:        return;
        !          1650: 
        !          1651:     if (sb -> sb_fd != NOTOK) {
        !          1652:        struct TSAPdata         txs;
        !          1653:        struct TSAPdisconnect   tds;
        !          1654: 
        !          1655:                                /* SunLink says this is proper behavior...
        !          1656:                                   using NOTOK, I've changed it to 10 secs */
        !          1657:        if (sb -> sb_flags & SB_FINN)
        !          1658:            while (TReadRequest (sb -> sb_fd, &txs, 10, &tds) != NOTOK) {
        !          1659:                TXFREE (&txs);
        !          1660:            }
        !          1661: 
        !          1662:        (void) TDiscRequest (sb -> sb_fd, NULLCP, 0, &tds);
        !          1663:     }
        !          1664: 
        !          1665:     if (sb -> sb_retry) {
        !          1666:        sb -> sb_retry -> s_mask &= ~SMASK_UDATA_PGI;
        !          1667:        sb -> sb_retry -> s_udata = NULL, sb -> sb_retry -> s_ulen = 0;
        !          1668:        freespkt (sb -> sb_retry);
        !          1669:     }
        !          1670: 
        !          1671:     if (sb -> sb_xspdu)
        !          1672:        freespkt (sb -> sb_xspdu);
        !          1673:     if (sb -> sb_spdu)
        !          1674:        freespkt (sb -> sb_spdu);
        !          1675: 
        !          1676:     QBFREE (&sb -> sb_qbuf);
        !          1677: 
        !          1678:     remque (sb);
        !          1679: 
        !          1680:     free ((char *) sb);
        !          1681: }
        !          1682: 
        !          1683: /*  */
        !          1684: 
        !          1685: struct ssapblk   *findsblk (sd)
        !          1686: register int sd;
        !          1687: {
        !          1688:     register struct ssapblk *sb;
        !          1689: 
        !          1690:     if (once_only == 0)
        !          1691:        return NULL;
        !          1692: 
        !          1693:     for (sb = SHead -> sb_forw; sb != SHead; sb = sb -> sb_forw)
        !          1694:        if (sb -> sb_fd == sd)
        !          1695:            return sb;
        !          1696: 
        !          1697:     return NULL;
        !          1698: }

unix.superglobalmegacorp.com

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