Annotation of 43BSDReno/contrib/isode-beta/support/isoc.c, revision 1.1

1.1     ! root        1: /* isoc.c - "minimal" ISODE client for testing */
        !             2: 
        !             3: #ifndef        lint
        !             4: static char *rcsid = "$Header: /f/osi/support/RCS/isoc.c,v 7.1 89/12/07 21:19:51 mrose Exp $";
        !             5: #endif
        !             6: 
        !             7: /* 
        !             8:  * $Header: /f/osi/support/RCS/isoc.c,v 7.1 89/12/07 21:19:51 mrose Exp $
        !             9:  *
        !            10:  *
        !            11:  * $Log:       isoc.c,v $
        !            12:  * Revision 7.1  89/12/07  21:19:51  mrose
        !            13:  * stuff
        !            14:  * 
        !            15:  * Revision 7.0  89/11/23  22:27:15  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: #include <stdio.h>
        !            32: #include <varargs.h>
        !            33: #include "rosap.h"
        !            34: #include "rtsap.h"
        !            35: #include "acsap.h"
        !            36: #include "psap2.h"
        !            37: #include "ssap.h"
        !            38: #include "tsap.h"
        !            39: #ifdef TCP
        !            40: #include "internet.h"
        !            41: #ifdef BSD42
        !            42: #include <sys/ioctl.h>
        !            43: #endif
        !            44: #ifdef SVR3
        !            45: #include <fcntl.h>
        !            46: #endif
        !            47: #endif
        !            48: #include "isoservent.h"
        !            49: #include "tailor.h"
        !            50: #include <sys/stat.h>
        !            51: 
        !            52: #undef TIMER
        !            53: #undef TMS
        !            54: #ifdef BSD42
        !            55: #define        TIMER
        !            56: #endif
        !            57: #ifdef SYS5
        !            58: #define        TIMER
        !            59: #ifndef        HPUX
        !            60: #include <sys/times.h>
        !            61: #define        TMS
        !            62: #endif
        !            63: #endif
        !            64: 
        !            65: #if    !defined (TCP) || defined (FIONBIO) || defined (SVR3)
        !            66: #define        ASYNC
        !            67: #endif
        !            68: 
        !            69: /*    DATA */
        !            70: 
        !            71: #define        ISN(req) \
        !            72:     (req & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY)) \
        !            73:        ? (long) ((getpid () % (SERIAL_MAX - SERIAL_MIN + 1)) + SERIAL_MIN) \
        !            74:        : SERIAL_NONE
        !            75: 
        !            76: static enum { echo, sink, XXX } mode = XXX;
        !            77: 
        !            78: static int   testing_queued_writes = 0;
        !            79: 
        !            80: static char *isacs = NULL;
        !            81: static int   isrts = 0;
        !            82: 
        !            83: static int   status = 0;
        !            84: 
        !            85: static char *myname = "isoc";
        !            86: 
        !            87: 
        !            88: void   adios (), advise ();
        !            89: void   ts_adios (), ts_advise ();
        !            90: void   ss_adios (), ss_advise ();
        !            91: void   ps_adios (), ps_advise ();
        !            92: void   acs_adios (), acs_advise ();
        !            93: void   rts_adios (), rts_advise ();
        !            94: void   ros_adios (), ros_advise ();
        !            95: 
        !            96: 
        !            97: long   lseek ();
        !            98: 
        !            99: /*    MAIN */
        !           100: 
        !           101: #define        chkacs()        if (isacs) \
        !           102:                            adios (NULLCP, "no association control for %s", \
        !           103:                                        argv[2])
        !           104: 
        !           105: /* ARGSUSED */
        !           106: 
        !           107: main (argc, argv, envp)
        !           108: int     argc;
        !           109: char  **argv,
        !           110:       **envp;
        !           111: {
        !           112:     register struct isoservent *is;
        !           113: 
        !           114:     if (myname = rindex (argv[0], '/'))
        !           115:        myname++;
        !           116:     if (myname == NULL || *myname == NULL)
        !           117:        myname = argv[0];
        !           118: 
        !           119:     isodetailor (myname, 1);
        !           120: 
        !           121:     if (argc != 4)
        !           122:        adios (NULLCP, "usage: %s host provider entity", myname);
        !           123: 
        !           124: #ifdef TCP
        !           125:     if (strcmp (argv[2], "raw") == 0) {
        !           126:        raw_main (argv[3], argv[1]);
        !           127:        exit (0);
        !           128:     }
        !           129: #endif
        !           130: 
        !           131:     if (index (argv[3], '/')) {
        !           132:        mode = strcmp (isacs = argv[3], "isode/sink") ? echo : sink;
        !           133:     }
        !           134:     else {
        !           135:        if ((is = getisoserventbyname (argv[3], argv[2])) == NULL)
        !           136:            adios (NULLCP, "%s/%s: unknown provider/entity pair",
        !           137:                    argv[2], argv[3]);
        !           138: 
        !           139:        mode = strcmp (is -> is_entity, "sink") ? echo : sink;
        !           140:     }
        !           141: 
        !           142:     if (strcmp (argv[2], "tsap") == 0) {
        !           143:        chkacs ();
        !           144:        ts_main (is, argv[1]);
        !           145:     }
        !           146:     else
        !           147:        if (strcmp (argv[2], "ssap") == 0) {
        !           148:            chkacs ();
        !           149:            ss_main (is, argv[1]);
        !           150:        }
        !           151:        else
        !           152:            if (strcmp (argv[2], "psap") == 0)
        !           153:                ps_main (is, argv[1]);
        !           154:            else
        !           155:                if (strcmp (argv[2], "rtsap") == 0) {
        !           156:                    isrts = 1;
        !           157:                    rts_main (is, argv[1]);
        !           158:                }
        !           159:                else
        !           160:                    if (strcmp (argv[2], "rosap") == 0)
        !           161:                        ros_main (is, argv[1]);
        !           162:                    else
        !           163:                        adios (NULLCP, "unknown provider: \"%s\"", argv[2]);
        !           164: 
        !           165:     exit (status);             /* NOTREACHED */
        !           166: }
        !           167: 
        !           168: /*    RAW */
        !           169: 
        !           170: #ifdef TCP
        !           171: static int  raw_main (service, addr)
        !           172: char   *service,
        !           173:        *addr;
        !           174: {
        !           175:     int     sd,
        !           176:             cc,
        !           177:             i,
        !           178:             j;
        !           179:     char   *cp,
        !           180:            *dp;
        !           181:     register struct hostent *hp;
        !           182:     register struct servent *sp;
        !           183:     struct sockaddr_in  in_socket;
        !           184:     register struct sockaddr_in *isock = &in_socket;
        !           185:     struct stat st;
        !           186: 
        !           187:     if (strcmp (service, "sink"))
        !           188:        adios (NULLCP, "only sink on raw tcp is supported");
        !           189:     if ((sp = getservbyname (service, "tcp")) == NULL)
        !           190:        adios (NULLCP, "%s/%s: unknown service", "tcp", service);
        !           191:     if ((hp = gethostbystring (addr)) == NULL)
        !           192:        adios (NULLCP, "%s: unknown host", addr);
        !           193: 
        !           194:     bzero ((char *) isock, sizeof *isock);
        !           195:     isock -> sin_family = hp -> h_addrtype;
        !           196:     isock -> sin_port = sp -> s_port;
        !           197:     inaddr_copy (hp, isock);
        !           198: 
        !           199:     if ((sd = start_tcp_client ((struct sockaddr_in *) 0, 0)) == NOTOK)
        !           200:        adios ("socket", "unable to start");
        !           201:     fprintf (stderr, "%s... ", hp -> h_name);
        !           202:     (void) fflush (stderr);
        !           203:     if (join_tcp_server (sd, isock) == NOTOK) {
        !           204:        fprintf (stderr, "failed\n");
        !           205:        adios ("socket", "unable to connect");
        !           206:     }
        !           207:     fprintf (stderr, "connected\n");
        !           208: 
        !           209:     if (fstat (fileno (stdin), &st) == NOTOK
        !           210:            || (st.st_mode & S_IFMT) != S_IFREG
        !           211:            || (cc = st.st_size) == 0)
        !           212:        adios (NULLCP, "standard input not a regular file");
        !           213:     (void) lseek (fileno (stdin), 0L, 0);
        !           214: 
        !           215:     if ((cp = malloc ((unsigned) cc)) == NULL)
        !           216:        adios (NULLCP, "no memory");
        !           217:     for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !           218:        switch (i = read (fileno (stdin), dp, j)) {
        !           219:            case NOTOK: 
        !           220:                adios ("on stdin", "read failed");
        !           221: 
        !           222:            case OK: 
        !           223:                adios (NULLCP, "premature end-of-file");
        !           224: 
        !           225:            default: 
        !           226:                break;
        !           227:        }
        !           228: 
        !           229: #ifdef TIMER
        !           230:     timer (0);
        !           231: #endif
        !           232:     if (write_tcp_socket (sd, cp, cc) != cc)
        !           233:        adios ("writing", "error");
        !           234:     (void) close_tcp_socket (sd);
        !           235: #ifdef TIMER
        !           236:     timer (cc);
        !           237: #endif
        !           238: }
        !           239: #endif
        !           240: 
        !           241: /*    TSAP */
        !           242: 
        !           243: static int  ts_main (is, addr)
        !           244: struct isoservent *is;
        !           245: char   *addr;
        !           246: {
        !           247:     int     sd,
        !           248:            cc,
        !           249:            i,
        !           250:            j,
        !           251:            expedited,
        !           252:            expd;
        !           253:     char   *cp,
        !           254:           *dp,
        !           255:            buffer[BUFSIZ];
        !           256:     struct  TSAPaddr *ta;
        !           257:     struct TSAPconnect  tcs;
        !           258:     register struct TSAPconnect *tc = &tcs;
        !           259:     struct TSAPdisconnect   tds;
        !           260:     register struct TSAPdisconnect *td = &tds;
        !           261:     struct stat st;
        !           262: 
        !           263:     if ((ta = is2taddr (addr, NULLCP, is)) == NULL)
        !           264:        adios (NULLCP, "address translation failed");
        !           265: 
        !           266:     fprintf (stderr, "%s... ", addr);
        !           267:     (void) fflush (stderr);
        !           268: #ifndef        ASYNC
        !           269:     if (TConnRequest (NULLTA, ta, 1, NULLCP, 0, NULLQOS, tc, td) == NOTOK) {
        !           270:        fprintf (stderr, "failed\n");
        !           271:        ts_adios (td, "T-CONNECT.REQUEST");
        !           272:     }
        !           273:     sd = tc -> tc_sd;
        !           274: #else
        !           275:     if ((i = TAsynConnRequest (NULLTA, ta, 1, NULLCP, 0, NULLQOS, tc, td, 1))
        !           276:            == NOTOK) {
        !           277:        fprintf (stderr, "failed\n");
        !           278:        ts_adios (td, "T-(ASYN-)CONNECT.REQUEST");
        !           279:     }
        !           280:     sd = tc -> tc_sd, cc = 0;
        !           281:     while (i == CONNECTING_1 || i == CONNECTING_2) {
        !           282:        int     nfds;
        !           283:        fd_set  mask,
        !           284:               *rmask,
        !           285:               *wmask;
        !           286: 
        !           287:        nfds = 0;
        !           288:        FD_ZERO (&mask);
        !           289:        if (TSelectMask (sd, &mask, &nfds, td) == NOTOK) {
        !           290:            fprintf (stderr, "failed\n");
        !           291:            ts_adios (td, "T-(ASYN-)CONNECT.REQUEST(TSelectMask)");
        !           292:        }
        !           293:        rmask = (i == CONNECTING_2) ? &mask : NULLFD;
        !           294:        wmask = (i == CONNECTING_2) ? NULLFD : &mask;
        !           295: 
        !           296:        fprintf (stderr, ".");
        !           297:        (void) fflush (stderr);
        !           298:        if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
        !           299:            fprintf (stderr, "failed\n");
        !           300:            adios ("failed", "select");
        !           301:        }
        !           302: 
        !           303:        if ((rmask && FD_ISSET (sd, rmask) == 0)
        !           304:                || (wmask && FD_ISSET (sd, wmask) == 0))
        !           305:            continue;
        !           306:            
        !           307:        if ((i = TAsynRetryRequest (sd, tc, td)) == NOTOK) {
        !           308:            fprintf (stderr, "failed\n");
        !           309:            ts_adios (td, "T-ASYN-RETRY.REQUEST");
        !           310:        }
        !           311:     }
        !           312: #endif
        !           313:     fprintf (stderr, "connected\n");
        !           314: 
        !           315: 
        !           316:     if (getenv ("TEST_QUEUED_WRITES")) {
        !           317:        if (TSetQueuesOK (tc -> tc_sd, 1, td) == NOTOK)
        !           318:            ts_adios (td, "T-SET-QUEUES-OK");
        !           319: 
        !           320:        tsap_log -> ll_events |= LLOG_EXCEPTIONS;
        !           321:        tsap_log -> ll_file = "-";
        !           322:        (void) ll_close (tsap_log);
        !           323: 
        !           324:        testing_queued_writes = 1;
        !           325:     }
        !           326: 
        !           327:     expd = tc -> tc_expedited;
        !           328: #ifdef DEBUG
        !           329:     {
        !           330:        advise (NULLCP, "responding TSAP address: %s",
        !           331:                taddr2str (&tc -> tc_responding));
        !           332: 
        !           333:        if (tc -> tc_cc > 0)
        !           334:            advise (NULLCP, "greetings: %d octets", tc -> tc_cc);
        !           335:     }
        !           336: #endif
        !           337: 
        !           338:     if (fstat (fileno (stdin), &st) != NOTOK
        !           339:            && (st.st_mode & S_IFMT) == S_IFREG
        !           340:            && (cc = st.st_size) != 0) {
        !           341:        (void) lseek (fileno (stdin), 0L, 0);
        !           342: 
        !           343:        if ((cp = malloc ((unsigned) cc)) == NULL)
        !           344:            adios (NULLCP, "no memory");
        !           345:        for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !           346:            switch (i = read (fileno (stdin), dp, j)) {
        !           347:                case NOTOK:
        !           348:                    adios ("on stdin", "read failed");
        !           349: 
        !           350:                case OK:
        !           351:                    adios (NULLCP, "premature end-of-file");
        !           352:                    
        !           353:                default:
        !           354:                    break;
        !           355:            }
        !           356:        for (i = 10; i > 0; i--) {
        !           357: #ifdef TIMER
        !           358:            timer (0);
        !           359: #endif
        !           360:            ts_datarequest (sd, cp, cc, 0);
        !           361: #ifdef TIMER
        !           362:            timer (cc);
        !           363: #endif
        !           364:        }
        !           365:        free (cp);
        !           366:     }
        !           367:     else
        !           368:        for (expedited = 0;
        !           369:                fgets (buffer, sizeof buffer, stdin);
        !           370:                expedited = !expedited) {
        !           371:            if ((cc = strlen (buffer) + 1) > TX_SIZE && expedited)
        !           372:                expedited = 0;
        !           373: 
        !           374:            ts_datarequest (sd, buffer, cc, expd ? expedited : 0);
        !           375:        }
        !           376: 
        !           377:     if (TDiscRequest (sd, NULLCP, 0, td) == NOTOK)
        !           378:        ts_adios (td, "T-DISCONNECT.REQUEST");
        !           379: }
        !           380: 
        !           381: /*  */
        !           382: 
        !           383: static int  ts_datarequest (sd, data, cc, expedited)
        !           384: int    sd;
        !           385: char   *data;
        !           386: int    cc,
        !           387:        expedited;
        !           388: {
        !           389:     struct TSAPdata txs;
        !           390:     register struct TSAPdata   *tx = &txs;
        !           391:     struct TSAPdisconnect   tds;
        !           392:     register struct TSAPdisconnect *td = &tds;
        !           393: 
        !           394:     if ((expedited ? TExpdRequest (sd, data, cc, td)
        !           395:                : TDataRequest (sd, data, cc, td)) == NOTOK)
        !           396:        if (expedited)
        !           397:            ts_adios (td, "T-EXPEDITED-DATA.REQUEST");
        !           398:        else
        !           399:            ts_adios (td, "T-DATA.REQUEST");
        !           400: 
        !           401:     if (mode == echo) {
        !           402:        if (testing_queued_writes) {
        !           403:            int     vecp;
        !           404:            char   *vec[4];
        !           405:            fd_set  rfds;
        !           406: 
        !           407:            FD_ZERO (&rfds);
        !           408:            FD_SET (sd, &rfds);
        !           409:            if (TNetAccept (&vecp, vec, sd + 1, &rfds, NULLFD, NULLFD, NOTOK,
        !           410:                            td) == NOTOK)
        !           411:                ts_adios (td, "T-NET-ACCEPT");
        !           412:        }
        !           413: 
        !           414:        if (TReadRequest (sd, tx, NOTOK, td) == NOTOK)
        !           415:            ts_adios (td, "T-READ.REQUEST");
        !           416:        if (cc != tx -> tx_cc) {
        !           417:            advise (NULLCP, "length mismatch, orig=%d echo=%d",
        !           418:                    cc, tx -> tx_cc);
        !           419:            status++;
        !           420:        }
        !           421:        else
        !           422:            if (qcmp (data, &tx -> tx_qbuf, cc))
        !           423:                status++;
        !           424:        TXFREE (tx)
        !           425:     }
        !           426: }
        !           427: 
        !           428: /*  */
        !           429: 
        !           430: static void  ts_adios (td, event)
        !           431: register struct TSAPdisconnect *td;
        !           432: char   *event;
        !           433: {
        !           434:     ts_advise (td, event);
        !           435: 
        !           436:     _exit (1);
        !           437: }
        !           438: 
        !           439: 
        !           440: static void  ts_advise (td, event)
        !           441: register struct TSAPdisconnect *td;
        !           442: char   *event;
        !           443: {
        !           444:     char    data[BUFSIZ];
        !           445: 
        !           446:     if (td -> td_cc > 0) {
        !           447:        (void) sprintf (data, "[%s] %*.*s",
        !           448:                TErrString (td -> td_reason),
        !           449:                td -> td_cc, td -> td_cc, td -> td_data);
        !           450:     }
        !           451:     else
        !           452:        (void) sprintf (data, "[%s]", TErrString (td -> td_reason));
        !           453: 
        !           454:     advise (NULLCP, "%s: %s", event, data);
        !           455: }
        !           456: 
        !           457: /*    SSAP */
        !           458: 
        !           459: static int requirements = SR_HALFDUPLEX | SR_DUPLEX | SR_EXPEDITED
        !           460:                | SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY
        !           461:                | SR_NEGOTIATED | SR_CAPABILITY | SR_EXCEPTIONS | SR_TYPEDATA;
        !           462: 
        !           463: static int owned = 0;
        !           464: static int avail = 0;
        !           465: 
        !           466: static long ssn;
        !           467: 
        !           468: static int nmodes;
        !           469: static int datamodes[4];
        !           470: 
        !           471: static char userdata[1024];
        !           472: 
        !           473: /*  */
        !           474: 
        !           475: static int  ss_main (is, addr)
        !           476: struct isoservent *is;
        !           477: char   *addr;
        !           478: {
        !           479:     int     sd,
        !           480:            cc,
        !           481:            i,
        !           482:            j,
        !           483:            k,
        !           484:            l,
        !           485:            tokens;
        !           486:     char   *cp,
        !           487:           *dp,
        !           488:            buffer[BUFSIZ];
        !           489:     struct SSAPactid    ids;
        !           490:     register struct SSAPactid  *id = &ids;
        !           491:     register struct SSAPaddr *sz;
        !           492:     struct SSAPref  sfs;
        !           493:     register struct SSAPref *sf;
        !           494:     struct SSAPconnect  scs;
        !           495:     register struct SSAPconnect *sc = &scs;
        !           496:     struct SSAPrelease  srs;
        !           497:     register struct SSAPrelease *sr = &srs;
        !           498:     struct SSAPindication   sis;
        !           499:     register struct SSAPindication *si = &sis;
        !           500:     register struct SSAPabort  *sa = &si -> si_abort;
        !           501:     struct stat st;
        !           502: 
        !           503:     bzero (userdata, sizeof userdata);
        !           504: 
        !           505:     if ((sz = is2saddr (addr, NULLCP, is)) == NULL)
        !           506:        adios (NULLCP, "address translation failed");
        !           507:     if ((sf = addr2ref (SLocalHostName ())) == NULL) {
        !           508:        sf = &sfs;
        !           509:        (void) bzero ((char *) sf, sizeof *sf);
        !           510:     }
        !           511: 
        !           512:     tokens = 0;
        !           513: #define dotoken(requires,shift,bit,type) \
        !           514: { \
        !           515:     if (requirements & requires) \
        !           516:        tokens |= ST_CALL_VALUE << shift; \
        !           517: }
        !           518:     dotokens ();
        !           519: #undef dotoken
        !           520: 
        !           521:     fprintf (stderr, "%s... ", addr);
        !           522:     (void) fflush (stderr);
        !           523: #ifndef        ASYNC
        !           524:     if (SConnRequest (sf, NULLSA, sz, requirements, tokens, ISN (requirements),
        !           525:            userdata, sizeof userdata /*SS_SIZE*/, NULLQOS, sc, si) == NOTOK) {
        !           526:        fprintf (stderr, "failed\n");
        !           527:        ss_adios (sa, "S-CONNECT.REQUEST");
        !           528:     }
        !           529:     sd = sc -> sc_sd;
        !           530: #else
        !           531:     if ((i = SAsynConnRequest (sf, NULLSA, sz, requirements, tokens,
        !           532:            ISN (requirements), userdata, sizeof userdata /*SS_SIZE*/, NULLQOS,
        !           533:            sc, si, 1))
        !           534:          == NOTOK) {
        !           535:        fprintf (stderr, "failed\n");
        !           536:        ss_adios (sa, "S-(ASYN-)CONNECT.REQUEST");
        !           537:     }
        !           538:     sd = sc -> sc_sd, cc = 0;
        !           539:     while (i == CONNECTING_1 || i == CONNECTING_2) {
        !           540:        int     nfds;
        !           541:        fd_set  mask,
        !           542:               *rmask,
        !           543:               *wmask;
        !           544: 
        !           545:        nfds = 0;
        !           546:        FD_ZERO (&mask);
        !           547:        if (SSelectMask (sd, &mask, &nfds, si) == NOTOK) {
        !           548:            fprintf (stderr, "failed\n");
        !           549:            ss_adios (sa, "S-(ASYN-)CONNECT.REQUEST(SSelectMask)");
        !           550:        }
        !           551:        rmask = (i == CONNECTING_2) ? &mask : NULLFD;
        !           552:        wmask = (i == CONNECTING_2) ? NULLFD : &mask;
        !           553: 
        !           554:        fprintf (stderr, ".");
        !           555:        if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
        !           556:            fprintf (stderr, "failed\n");
        !           557:            adios ("failed", "select");
        !           558:        }
        !           559: 
        !           560:        if ((rmask && FD_ISSET (sd, rmask) == 0)
        !           561:                || (wmask && FD_ISSET (sd, wmask) == 0))
        !           562:            continue;
        !           563:            
        !           564:        if ((i = SAsynRetryRequest (sd, sc, si)) == NOTOK) {
        !           565:            fprintf (stderr, "failed\n");
        !           566:            ss_adios (sa, "S-ASYN-RETRY.REQUEST");
        !           567:        }
        !           568:     }
        !           569: #endif
        !           570: 
        !           571:     if (sc -> sc_result != SC_ACCEPT) {
        !           572:        fprintf (stderr, "failed\n");
        !           573:        if (sc -> sc_cc > 0)
        !           574:            adios (NULLCP, "connection rejected: [%s] %*.*s",
        !           575:                        SErrString (sc -> sc_result),
        !           576:                        sc -> sc_cc, sc -> sc_cc, sc -> sc_data);
        !           577:        else
        !           578:            adios (NULLCP, "connection rejected: [%s]",
        !           579:                        SErrString (sc -> sc_result));
        !           580:     }
        !           581:     fprintf (stderr, "connected\n");
        !           582: 
        !           583: #ifdef DEBUG
        !           584:     {
        !           585:        advise (NULLCP, "responding SSAP address: %s",
        !           586:                saddr2str (&sc -> sc_responding));
        !           587: 
        !           588:        if (sc -> sc_cc > 0)
        !           589:            advise (NULLCP, "greetings: %d octets", sc -> sc_cc);
        !           590:     }
        !           591: #endif
        !           592:     requirements = sc -> sc_requirements;
        !           593:     nmodes = 0;
        !           594:     datamodes[nmodes++] = SX_NORMAL;
        !           595:     if (requirements & SR_EXPEDITED)
        !           596:        datamodes[nmodes++] = SX_EXPEDITED;
        !           597:     if ((requirements & SR_CAPABILITY) && (requirements & SR_ACTIVITY))
        !           598:        datamodes[nmodes++] = SX_CAPDIND;
        !           599:     if (requirements & SR_TYPEDATA)
        !           600:        datamodes[nmodes++] = SX_TYPED;
        !           601: 
        !           602: #define dotoken(requires,shift,bit,type) \
        !           603: { \
        !           604:     if (requirements & requires) \
        !           605:        switch (sc -> sc_settings & (ST_MASK << shift)) { \
        !           606:            case ST_CALL_VALUE: \
        !           607:                adios (NULLCP, "%s token: choice", type); \
        !           608:  \
        !           609:            case ST_INIT_VALUE: \
        !           610:                owned |= bit, avail |= bit; \
        !           611:                break; \
        !           612:  \
        !           613:            case ST_RESP_VALUE: \
        !           614:                avail |= bit; \
        !           615:                break; \
        !           616:  \
        !           617:            default: \
        !           618:                adios (NULLCP, "%s token: reserved", type); \
        !           619:        } \
        !           620: }
        !           621:        dotokens ();
        !           622: #undef dotoken
        !           623: 
        !           624:     if (requirements & SR_ACTIVITY) {
        !           625:        (void) strcpy (id -> sd_data, mode == echo ? "echo" : "sink");
        !           626:        id -> sd_len = strlen (id -> sd_data);
        !           627:        if (SActStartRequest (sd, id, userdata, SV_SIZE, si) == NOTOK)
        !           628:            ss_adios (sa, "S-ACTIVITY-START.REQUEST");
        !           629:     }
        !           630: 
        !           631:     if (fstat (fileno (stdin), &st) != NOTOK
        !           632:            && (st.st_mode & S_IFMT) == S_IFREG
        !           633:            && (cc = st.st_size) != 0) {
        !           634:        (void) lseek (fileno (stdin), 0L, 0);
        !           635: 
        !           636:        if ((cp = malloc ((unsigned) cc)) == NULL)
        !           637:            adios (NULLCP, "no memory");
        !           638:        for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !           639:            switch (i = read (fileno (stdin), dp, j)) {
        !           640:                case NOTOK:
        !           641:                    adios ("on stdin", "read failed");
        !           642: 
        !           643:                case OK:
        !           644:                    adios (NULLCP, "premature end-of-file");
        !           645:                    
        !           646:                default:
        !           647:                    break;
        !           648:            }
        !           649:        for (i = 10; i > 0; i--) {
        !           650: #ifdef TIMER
        !           651:            timer (0);
        !           652: #endif
        !           653:            ss_datarequest (sd, cp, cc, SX_NORMAL, 0);
        !           654: #ifdef TIMER
        !           655:            timer (cc);
        !           656: #endif
        !           657:        }
        !           658:        free (cp);
        !           659:     }
        !           660:     else {
        !           661:        for (j = l = 0; fgets (buffer, sizeof buffer, stdin); ) {
        !           662:            k = j >= nmodes ? SX_EXPEDITED : datamodes[j++ % nmodes];
        !           663:            if ((cc = strlen (buffer) + 1) > SX_EXSIZE && k == SX_EXPEDITED) {
        !           664:                if ((k = datamodes[j++ % nmodes]) == SX_EXPEDITED)
        !           665:                    k = datamodes[j++ % nmodes];
        !           666:            }
        !           667: 
        !           668:            switch (k) {
        !           669:                case SX_CAPDIND:
        !           670:                    if (!(requirements & SR_RESYNC) || l++ & 0x01) {
        !           671:                        ss_waitfor (sd, ST_ACT_TOKEN);
        !           672:                        if (l & 0x03) {
        !           673:                            if (SActIntrRequest (sd, SP_SEQUENCE, si)
        !           674:                                    == NOTOK)
        !           675:                                ss_adios (sa, "S-ACTIVITY-INTERRUPT.REQUEST");
        !           676:                        }
        !           677:                        else {
        !           678:                            if (SActDiscRequest (sd, SP_SEQUENCE, si)
        !           679:                                    == NOTOK)
        !           680:                                ss_adios (sa, "S-ACTIVITY-DISCARD.REQUEST");
        !           681:                        }
        !           682:                        ss_waitfor (sd, -1);
        !           683:                        goto push_data;
        !           684:                    }
        !           685:                    if (!(requirements & SR_RESYNC))
        !           686:                        break;
        !           687:                    tokens = 0;
        !           688: #define dotoken(requires,shift,bit,type) \
        !           689: { \
        !           690:                    if (requirements & requires) \
        !           691:                        tokens |= ST_CALL_VALUE << shift; \
        !           692: }
        !           693:                    dotokens ();
        !           694: #undef dotoken
        !           695:                    if (SReSyncRequest (sd, SYNC_SET, ssn - 1, tokens,
        !           696:                                userdata, SN_SIZE, si) == NOTOK)
        !           697:                        ss_adios (sa, "S-RESYNCHRONIZE.REQUEST");
        !           698:                    ss_waitfor (sd, -1);
        !           699:                    break;
        !           700: 
        !           701:                case SX_EXPEDITED:
        !           702:                    if (j >= nmodes)
        !           703:                        j = j % nmodes;/* fall... */
        !           704:                    if (!(requirements & SR_EXPEDITED))
        !           705:                        k = SX_NORMAL;  /* fall... */
        !           706:                default:
        !           707: push_data: ;
        !           708:                    ss_datarequest (sd, buffer, cc, k, 1);
        !           709:                    if (k == SX_CAPDIND
        !           710:                            && SActResumeRequest (sd, id, id, 
        !           711:                                    (long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1))
        !           712:                                    + SERIAL_MIN, sf, userdata, SV_SIZE, si)
        !           713:                                  == NOTOK)
        !           714:                        ss_adios (sa, "S-ACTIVITY-RESUME.REQUEST");
        !           715:                    break;
        !           716:            }
        !           717:        }
        !           718: 
        !           719:        if (requirements & SR_EXCEPTIONS) {
        !           720:            if (owned & ST_DAT_TOKEN)
        !           721:                if (SGTokenRequest (sd, ST_DAT_TOKEN, si) == NOTOK)
        !           722:                    ss_adios (sa, "S-TOKEN-GIVE.REQUEST");
        !           723:                else
        !           724:                    owned &= ~ST_DAT_TOKEN;
        !           725:            if (SUReportRequest (sd, SP_NOREASON, userdata, SP_SIZE, si)
        !           726:                    == NOTOK)
        !           727:                ss_adios (sa, "S-U-EXCEPTION-REPORT.REQUEST");
        !           728:            ss_waitfor (sd, -1);
        !           729:        }    
        !           730:     }
        !           731: 
        !           732:     if ((requirements & SR_MAJORSYNC) && !(requirements & SR_ACTIVITY)) {
        !           733:        if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si) == NOTOK)
        !           734:            switch (sa -> sa_reason) {
        !           735:                case SC_OPERATION:
        !           736:                    ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
        !           737:                            | ST_MAJ_TOKEN);
        !           738:                    if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si)
        !           739:                            == OK)
        !           740:                        break;  /* else fall */
        !           741: 
        !           742:                default:
        !           743:                    ss_adios (sa, "S-MAJOR-SYNC.REQUEST");
        !           744:            }
        !           745: 
        !           746:        ss_waitfor (sd, -1);
        !           747:     }
        !           748: 
        !           749:     if (requirements & SR_ACTIVITY) {
        !           750:        if (SActEndRequest (sd, &ssn, userdata, SV_SIZE, si) == NOTOK)
        !           751:            switch (sa -> sa_reason) {
        !           752:                case SC_OPERATION:
        !           753:                    ss_waitfor (sd, avail);
        !           754:                    if (SActEndRequest (sd, &ssn, userdata, SV_SIZE, si) == OK)
        !           755:                        break;  /* else fall */
        !           756: 
        !           757:                default:
        !           758:                    ss_adios (sa, "S-ACTIVITY-END.REQUEST");
        !           759:            }
        !           760: 
        !           761:        ss_waitfor (sd, -1);
        !           762:                
        !           763:        if (SGControlRequest (sd, si) == NOTOK)
        !           764:            switch (sa -> sa_reason) {
        !           765:                case SC_OPERATION:
        !           766:                    ss_waitfor (sd, avail);
        !           767:                    if (SGControlRequest (sd, si) == OK)
        !           768:                        break;  /* else fall */
        !           769: 
        !           770:                default:
        !           771:                    ss_adios (sa, "S-CONTROL-GIVE.REQUEST");
        !           772:            }
        !           773: 
        !           774:        owned = 0;
        !           775: 
        !           776:        ss_waitfor (sd, -1);
        !           777:     }
        !           778: 
        !           779:     if (SRelRequest (sd, userdata, SF_SIZE, NOTOK, sr, si) == NOTOK)
        !           780:        switch (sa -> sa_reason) {
        !           781:            case SC_OPERATION: 
        !           782:            case SC_WAITING: 
        !           783:                ss_waitfor (sd, avail);
        !           784:                if (SRelRequest (sd, userdata, SF_SIZE, NOTOK, sr, si) == OK)
        !           785:                    break;      /* else fall */
        !           786: 
        !           787:            default: 
        !           788:                ss_adios (sa, "S-RELEASE.REQUEST");
        !           789:        }
        !           790: 
        !           791:        if (!sr -> sr_affirmative) {
        !           792:            (void) SUAbortRequest (sd, NULLCP, 0, si);
        !           793: 
        !           794:            if (sr -> sr_cc > 0)
        !           795:                adios (NULLCP, "release rejected by peer: %*.*s",
        !           796:                        sr -> sr_cc, sr -> sr_cc, sr -> sr_data);
        !           797:            else
        !           798:                adios (NULLCP, "release rejected by peer");
        !           799:        }
        !           800:        SRFREE (sr);
        !           801: }
        !           802: 
        !           803: /*  */
        !           804: 
        !           805: static int ss_datarequest (sd, data, cc, dm, sync)
        !           806: int    sd;
        !           807: char   *data;
        !           808: int    cc,
        !           809:        dm,
        !           810:        sync;
        !           811: {
        !           812:     int     result;
        !           813:     struct SSAPdata sxs;
        !           814:     register struct SSAPdata   *sx = &sxs;
        !           815:     struct SSAPindication   sis;
        !           816:     register struct SSAPindication *si = &sis;
        !           817:     register struct SSAPabort  *sa = &si -> si_abort;
        !           818: 
        !           819:     switch (dm) {
        !           820:        default: 
        !           821:            if (SDataRequest (sd, data, cc, si) == NOTOK)
        !           822:                switch (sa -> sa_reason) {
        !           823:                    case SC_OPERATION: 
        !           824:                        ss_waitfor (sd, ST_DAT_TOKEN);
        !           825:                        if (SDataRequest (sd, data, cc, si) == OK)
        !           826:                            break;/* else fall */
        !           827: 
        !           828:                    default: 
        !           829:                        ss_adios (sa, "S-DATA.REQUEST");
        !           830:                }
        !           831:            break;
        !           832: 
        !           833:        case SX_EXPEDITED: 
        !           834:            if (SExpdRequest (sd, data, cc, si) == NOTOK)
        !           835:                ss_adios (sa, "S-EXPEDITED-DATA.REQUEST");
        !           836:            break;
        !           837: 
        !           838:        case SX_CAPDIND: 
        !           839:            if (SCapdRequest (sd, data, cc, si) == NOTOK)
        !           840:                switch (sa -> sa_reason) {
        !           841:                    case SC_OPERATION: 
        !           842:                        ss_waitfor (sd, avail & ~ST_RLS_TOKEN);
        !           843:                        if (SCapdRequest (sd, data, cc, si) == OK)
        !           844:                            break;/* else fall */
        !           845: 
        !           846:                    default: 
        !           847:                        ss_adios (sa, "S-CAPABILITY-DATA.REQUEST");
        !           848:                }
        !           849:            break;
        !           850: 
        !           851:        case SX_TYPED: 
        !           852:            if (STypedRequest (sd, data, cc, si) == NOTOK)
        !           853:                ss_adios (sa, "S-TYPED-DATA.REQUEST");
        !           854:            break;
        !           855:     }
        !           856: 
        !           857:     if (mode == echo || dm == SX_CAPDIND)
        !           858:        for (;;) {
        !           859:            switch (result = SReadRequest (sd, sx, NOTOK, si)) {
        !           860:                case NOTOK: 
        !           861:                    ss_adios (sa, "S-READ.REQUEST");
        !           862: 
        !           863:                case OK: 
        !           864:                    if ((dm != SX_CAPDIND ? dm : SX_CAPDCNF)
        !           865:                            != sx -> sx_type) {
        !           866:                        advise (NULLCP,
        !           867:                                "data indication type mismatch, orig=%d echo=%d",
        !           868:                                dm, sx -> sx_type);
        !           869:                        status++;
        !           870:                    }
        !           871:                    if (cc != sx -> sx_cc) {
        !           872:                        advise (NULLCP, "length mismatch, orig=%d echo=%d",
        !           873:                                cc, sx -> sx_cc);
        !           874:                        status++;
        !           875:                    }
        !           876:                    else
        !           877:                        if (qcmp (data, &sx -> sx_qbuf, cc))
        !           878:                            status++;
        !           879:                    SXFREE (sx)
        !           880:                    break;
        !           881: 
        !           882:                case DONE: 
        !           883:                    ss_event (sd, si);
        !           884:                    continue;
        !           885: 
        !           886:                default: 
        !           887:                    adios (NULLCP, "unknown return from SReadRequest=%d",
        !           888:                            result);
        !           889:            }
        !           890:            break;
        !           891:        }
        !           892: 
        !           893:     if (sync &&
        !           894:            (requirements & SR_MINORSYNC) && !(requirements & SR_ACTIVITY)) {
        !           895:        if (SMinSyncRequest (sd, SYNC_CONFIRM, &ssn, userdata, SN_SIZE, si)
        !           896:                == NOTOK)
        !           897:            switch (sa -> sa_reason) {
        !           898:                case SC_OPERATION: 
        !           899:                    ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN);
        !           900:                    if (SMinSyncRequest (sd, SYNC_CONFIRM, &ssn, userdata,
        !           901:                            SN_SIZE, si) == OK)
        !           902:                        break;  /* else fall */
        !           903: 
        !           904:                default: 
        !           905:                    ss_adios (sa, "S-MINOR-SYNC.REQUEST");
        !           906:            }
        !           907: 
        !           908:        ss_waitfor (sd, -1);
        !           909:     }
        !           910:     else
        !           911:        if (sync
        !           912:                && (requirements & SR_ACTIVITY)
        !           913:                && (requirements & SR_MAJORSYNC)
        !           914:                && dm == SX_NORMAL) {
        !           915:            if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si) == NOTOK)
        !           916:                switch (sa -> sa_reason) {
        !           917:                    case SC_OPERATION: 
        !           918:                        ss_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
        !           919:                                | ST_MAJ_TOKEN);
        !           920:                        if (SMajSyncRequest (sd, &ssn, userdata, SN_SIZE, si)
        !           921:                                == OK)
        !           922:                            break;/* else fall */
        !           923: 
        !           924:                    default: 
        !           925:                        ss_adios (sa, "S-MAJOR-SYNC.REQUEST");
        !           926:                }
        !           927: 
        !           928:            ss_waitfor (sd, -1);
        !           929:        }
        !           930: }
        !           931: 
        !           932: /*  */
        !           933: 
        !           934: static int  ss_waitfor (sd, want)
        !           935: int    sd,
        !           936:        want;
        !           937: {
        !           938:     int     result,
        !           939:            tokens;
        !           940:     char    buffer[BUFSIZ];
        !           941:     struct SSAPdata sxs;
        !           942:     register struct SSAPdata   *sx = &sxs;
        !           943:     struct SSAPindication   sis;
        !           944:     register struct SSAPindication *si = &sis;
        !           945:     register struct SSAPabort  *sa = &si -> si_abort;
        !           946: 
        !           947:     for (;;) {
        !           948:        if (want == -1) {
        !           949:            want = avail;
        !           950:            goto read_it;
        !           951:        }
        !           952: 
        !           953:        tokens = 0;
        !           954: #define dotoken(requires,shift,bit,type) \
        !           955: { \
        !           956:        if ((want & bit) && !(owned & bit)) \
        !           957:            tokens |= bit; \
        !           958: }
        !           959:        dotokens ();
        !           960: #undef dotoken
        !           961:        if (tokens == 0)
        !           962:            return;
        !           963: 
        !           964:        if (SPTokenRequest (sd, tokens, userdata, ST_SIZE, si) == NOTOK)
        !           965:            ss_adios (sa, "S-TOKEN-PLEASE.REQUEST");
        !           966: 
        !           967: read_it: ;
        !           968:        switch (result = SReadRequest (sd, sx, NOTOK, si)) {
        !           969:            case NOTOK: 
        !           970:                ss_adios (sa, "S-READ.REQUEST");
        !           971: 
        !           972:            case OK: 
        !           973:                (void) strcpy (buffer, "protocol screw-up");
        !           974:                if (SUAbortRequest (sd, buffer, strlen (buffer) + 1, si) == NOTOK)
        !           975:                    ss_adios (sa, "S-U-ABORT.REQUEST");
        !           976:                adios (NULLCP, "%s, data indication type=0x%x",
        !           977:                        buffer, sx -> sx_type);
        !           978: 
        !           979:            case DONE: 
        !           980:                ss_event (sd, si);
        !           981:                break;
        !           982: 
        !           983:            default: 
        !           984:                adios (NULLCP, "unknown return from SReadRequest=%d",
        !           985:                        result);
        !           986:        }
        !           987:     }
        !           988: }
        !           989: 
        !           990: /*  */
        !           991: 
        !           992: static ss_event (sd, si)
        !           993: int    sd;
        !           994: register struct SSAPindication *si;
        !           995: {
        !           996:     register struct SSAPabort  *sa = &si -> si_abort;
        !           997:     register struct SSAPactivity *sv = &si -> si_activity;
        !           998:     register struct SSAPfinish *sf = &si -> si_finish;
        !           999:     register struct SSAPreport *sp = &si -> si_report;
        !          1000:     register struct SSAPsync   *sn = &si -> si_sync;
        !          1001:     register struct SSAPtoken  *st = &si -> si_token;
        !          1002: 
        !          1003:     switch (si -> si_type) {
        !          1004:        case SI_TOKEN: 
        !          1005:            switch (st -> st_type) {
        !          1006:                case ST_GIVE: 
        !          1007:                case ST_CONTROL: 
        !          1008:                    owned = st -> st_owned;
        !          1009:                    break;
        !          1010: 
        !          1011:                case ST_PLEASE: 
        !          1012:                    if (SGTokenRequest (sd,
        !          1013:                                (int) st -> st_tokens, si)
        !          1014:                            == NOTOK)
        !          1015:                        ss_adios (sa, "S-TOKEN-GIVE.REQUEST");
        !          1016:                    else
        !          1017:                        owned &= ~st -> st_tokens;
        !          1018:                    break;
        !          1019: 
        !          1020:                default: 
        !          1021:                    adios (NULLCP,
        !          1022:                            "unknown token indication type=0x%x, %d bytes",
        !          1023:                            st -> st_type, st -> st_cc);
        !          1024:            }
        !          1025:            STFREE (st);
        !          1026:            break;
        !          1027: 
        !          1028:        case SI_SYNC: 
        !          1029:            switch (sn -> sn_type) {
        !          1030:                case SN_MAJORIND: 
        !          1031:                    adios (NULLCP, "majorsync indication %d, %d bytes",
        !          1032:                            sn -> sn_ssn, sn -> sn_cc);
        !          1033:                    break;
        !          1034: 
        !          1035:                case SN_MAJORCNF: 
        !          1036:                    break;
        !          1037: 
        !          1038:                case SN_MINORIND: 
        !          1039:                    adios (NULLCP, "minorsync indication %d%s, %d bytes",
        !          1040:                            sn -> sn_ssn, sn -> sn_options == SYNC_CONFIRM
        !          1041:                            ? " (wants confirmation)" : NULLCP, sn -> sn_cc);
        !          1042:                    break;
        !          1043: 
        !          1044:                case SN_MINORCNF: 
        !          1045:                    break;
        !          1046: 
        !          1047:                case SN_RESETIND: 
        !          1048: #define        dotoken(requires,shift,bit,type) \
        !          1049: { \
        !          1050:                    if (requirements & requires) \
        !          1051:                        switch (sn -> sn_settings & (ST_MASK << shift)) { \
        !          1052:                            case ST_CALL_VALUE << shift: \
        !          1053:                                sn -> sn_settings &= ~(ST_MASK << shift); \
        !          1054:                                sn -> sn_settings |= ST_RESP_VALUE << shift; \
        !          1055:                            case ST_RESP_VALUE << shift: \
        !          1056:                                owned &= ~bit; \
        !          1057:                                break; \
        !          1058:  \
        !          1059:                            case ST_INIT_VALUE << shift: \
        !          1060:                                owned |= bit; \
        !          1061:                                break; \
        !          1062:  \
        !          1063:                            default: \
        !          1064:                                adios (NULLCP, "%s token: reserved", type); \
        !          1065:                                break; \
        !          1066:                        } \
        !          1067: }
        !          1068:                    dotokens ();
        !          1069: #undef dotoken
        !          1070:                    if (SReSyncResponse (sd, sn -> sn_ssn, sn -> sn_settings,
        !          1071:                                userdata, SN_SIZE, si) == NOTOK)
        !          1072:                        ss_adios (sa, "S-RESYNCHRONIZE.RESPONSE");
        !          1073:                    break;
        !          1074: 
        !          1075:                case SN_RESETCNF: 
        !          1076:                    break;
        !          1077: 
        !          1078:                default: 
        !          1079:                    adios (NULLCP,
        !          1080:                            "unknown sync indication=0x%x, ssn=%d, %d bytes",
        !          1081:                            sn -> sn_type, sn -> sn_ssn, sn -> sn_cc);
        !          1082:            }
        !          1083:            SNFREE (sn);
        !          1084:            break;
        !          1085: 
        !          1086:        case SI_ACTIVITY: 
        !          1087:            switch (sv -> sv_type) {
        !          1088:                case SV_START: 
        !          1089:                    adios (NULLCP,
        !          1090:                            "activity start indication: %*.*s, %d bytes",
        !          1091:                            sv -> sv_id.sd_len, sv -> sv_id.sd_len,
        !          1092:                            sv -> sv_id.sd_data, sv -> sv_cc);
        !          1093: 
        !          1094:                case SV_RESUME: 
        !          1095:                    adios (NULLCP, 
        !          1096:                            "activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d, %d bytes",
        !          1097:                            sv -> sv_id.sd_len, sv -> sv_id.sd_len,
        !          1098:                            sv -> sv_id.sd_data, sv -> sv_oid.sd_len,
        !          1099:                            sv -> sv_oid.sd_len, sv -> sv_oid.sd_data,
        !          1100:                            sprintref (&sv -> sv_connect), sv -> sv_ssn,
        !          1101:                            sv -> sv_cc);
        !          1102: 
        !          1103:                case SV_INTRIND: 
        !          1104:                    adios (NULLCP,
        !          1105:                            "activity interrupt indication %d, %d bytes",
        !          1106:                            sv -> sv_reason, sv -> sv_cc);
        !          1107: 
        !          1108:                case SV_INTRCNF: 
        !          1109:                    break;
        !          1110: 
        !          1111:                case SV_DISCIND: 
        !          1112:                    adios (NULLCP,
        !          1113:                            "activity discard indication %d, %d bytes",
        !          1114:                            sv -> sv_reason, sv -> sv_cc);
        !          1115: 
        !          1116:                case SV_DISCCNF: 
        !          1117:                    break;
        !          1118: 
        !          1119:                case SV_ENDIND: 
        !          1120:                    adios (NULLCP, "activity end indication %d, %d bytes",
        !          1121:                            sv -> sv_ssn, sv -> sv_cc);
        !          1122: 
        !          1123:                case SV_ENDCNF: 
        !          1124:                    break;
        !          1125: 
        !          1126:                default: 
        !          1127:                    adios (NULLCP,
        !          1128:                            "unknown activity indication=0x%x, %d bytes",
        !          1129:                            sv -> sv_type, sv -> sv_cc);
        !          1130:            }
        !          1131:            SVFREE (sv);
        !          1132:            break;
        !          1133: 
        !          1134:        case SI_REPORT: 
        !          1135:            if (requirements & SR_DAT_EXISTS) {
        !          1136:                if (SGTokenRequest (sd, ST_DAT_TOKEN, si) == NOTOK)
        !          1137:                    ss_adios (sa, "S-TOKEN-GIVE.REQUEST (to clear exception)");
        !          1138:                else
        !          1139:                    owned &= ~ST_DAT_TOKEN;
        !          1140:            }
        !          1141:            else
        !          1142:                if (SUAbortRequest (sd, NULLCP, 0, si) == NOTOK)
        !          1143:                    ss_adios (sa, "S-U-ABORT.REQUEST");
        !          1144:                else
        !          1145:                    adios (NULLCP, "aborted");
        !          1146:            SPFREE (sp);
        !          1147:            break;
        !          1148: 
        !          1149:        case SI_FINISH: 
        !          1150:            if (SRelResponse (sd, SC_REJECTED, NULLCP, 0, si) == NOTOK)
        !          1151:                ss_adios (sa, "S-RELEASE.RESPONSE");
        !          1152:            SFFREE (sf);
        !          1153:            break;
        !          1154: 
        !          1155:        default: 
        !          1156:            adios (NULLCP, "unknown indication type=0x%x",
        !          1157:                    si -> si_type);
        !          1158:     }
        !          1159: }
        !          1160: 
        !          1161: /*  */
        !          1162: 
        !          1163: static void  ss_adios (sa, event)
        !          1164: register struct SSAPabort *sa;
        !          1165: char   *event;
        !          1166: {
        !          1167:     ss_advise (sa, event);
        !          1168: 
        !          1169:     _exit (1);
        !          1170: }
        !          1171: 
        !          1172: 
        !          1173: static void  ss_advise (sa, event)
        !          1174: register struct SSAPabort *sa;
        !          1175: char   *event;
        !          1176: {
        !          1177:     char    buffer[BUFSIZ];
        !          1178: 
        !          1179:     if (sa -> sa_cc > 0)
        !          1180:        (void) sprintf (buffer, "[%s] %*.*s",
        !          1181:                SErrString (sa -> sa_reason),
        !          1182:                sa -> sa_cc, sa -> sa_cc, sa -> sa_data);
        !          1183:     else
        !          1184:        (void) sprintf (buffer, "[%s]", SErrString (sa -> sa_reason));
        !          1185: 
        !          1186:     advise (NULLCP, "%s: %s%s", event, buffer,
        !          1187:            sa -> sa_peer ? " (peer initiated)" : "");
        !          1188: 
        !          1189:     SAFREE (sa);
        !          1190: }
        !          1191: 
        !          1192: /*    PSAP */
        !          1193: 
        !          1194: static int prequirements = 0;
        !          1195: #define        srequirements requirements
        !          1196: 
        !          1197: static int nctxs;
        !          1198: static int datactxs[NPCTX];
        !          1199: 
        !          1200: /*  */
        !          1201: 
        !          1202: static int  ps_main (is, addr)
        !          1203: struct isoservent *is;
        !          1204: char   *addr;
        !          1205: {
        !          1206:     int     sd,
        !          1207:            cc,
        !          1208:            i,
        !          1209:            j,
        !          1210:            k,
        !          1211:            l,
        !          1212:            m,
        !          1213:            tokens;
        !          1214:     char   *cp,
        !          1215:           *dp,
        !          1216:            buffer[BUFSIZ];
        !          1217:     register struct PSAPaddr   *pz;
        !          1218:     struct SSAPactid    ids;
        !          1219:     register struct SSAPactid  *id = &ids;
        !          1220:     struct SSAPref  sfs;
        !          1221:     register struct SSAPref *sf;
        !          1222:     struct PSAPconnect  pcs;
        !          1223:     register struct PSAPconnect *pc = &pcs;
        !          1224:     struct PSAPctxlist pls;
        !          1225:     register struct PSAPctxlist *pl = &pls;
        !          1226:     struct PSAPrelease  prs;
        !          1227:     register struct PSAPrelease *pr = &prs;
        !          1228:     struct PSAPindication   pis;
        !          1229:     register struct PSAPindication *pi = &pis;
        !          1230:     register struct PSAPabort  *pa = &pi -> pi_abort;
        !          1231:     struct AcSAPconnect  accs;
        !          1232:     register struct AcSAPconnect *acc = &accs;
        !          1233:     struct AcSAPrelease acrs;
        !          1234:     register struct AcSAPrelease *acr = &acrs;
        !          1235:     struct AcSAPindication   acis;
        !          1236:     register struct AcSAPindication *aci = &acis;
        !          1237:     register struct AcSAPabort  *aca = &aci -> aci_abort;
        !          1238:     register PE            pe;
        !          1239:     PE     udata[NPDATA];
        !          1240:     AEI            aei;
        !          1241:     OID            oid,
        !          1242:            ode;
        !          1243:     struct stat st;
        !          1244: 
        !          1245:     if (isacs) {
        !          1246:        if ((aei = str2aei (addr, isacs)) == NULLAEI)
        !          1247:            adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
        !          1248:        if ((pz = aei2addr (aei)) == NULLPA)
        !          1249:            adios (NULLCP, "address translation failed");
        !          1250: 
        !          1251:        cp = mode == echo ? "isode echo pci" : "isode sink pci";
        !          1252:        if ((ode = ode2oid (cp)) == NULLOID)
        !          1253:            adios (NULLCP, "%s: unknown object descriptor", cp);
        !          1254:        ode = oid_cpy (ode);
        !          1255:     }
        !          1256:     else
        !          1257:        if ((pz = is2paddr (addr, NULLCP, is)) == NULL)
        !          1258:            adios (NULLCP, "address translation failed");
        !          1259:     if ((sf = addr2ref (PLocalHostName ())) == NULL) {
        !          1260:        sf = &sfs;
        !          1261:        (void) bzero ((char *) sf, sizeof *sf);
        !          1262:     }
        !          1263: 
        !          1264:     tokens = 0;
        !          1265: #define dotoken(requires,shift,bit,type) \
        !          1266: { \
        !          1267:     if (srequirements & requires) \
        !          1268:        tokens |= ST_CALL_VALUE << shift; \
        !          1269: }
        !          1270:     dotokens ();
        !          1271: #undef dotoken
        !          1272: 
        !          1273:     for (i = (pl -> pc_nctx = NPCTX - (isacs ? 1 : 0)) - 1; i >= 0; i--) {
        !          1274:        pl -> pc_ctx[i].pc_id = i * 2 + 1;
        !          1275:        if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
        !          1276:            adios (NULLCP, "iso asn.1 abstract syntax: unknown");
        !          1277:        pl -> pc_ctx[i].pc_asn = oid_cpy (oid);
        !          1278:        pl -> pc_ctx[i].pc_atn = NULLOID;
        !          1279:     }
        !          1280: 
        !          1281:     for (i = 0; i < NPDATA; i++) {
        !          1282:        if ((pe = int2prim (i)) == NULLPE)
        !          1283:            adios (NULLCP, "unable to allocate hello");
        !          1284:        pe -> pe_context = (i % pl -> pc_nctx) * 2 + 1;
        !          1285:        udata[i] = pe;
        !          1286:     }
        !          1287: 
        !          1288:     fprintf (stderr, "%s... ", addr);
        !          1289:     (void) fflush (stderr);
        !          1290:     if (isacs) {
        !          1291: #ifndef        ASYNC
        !          1292:        if (AcAssocRequest (ode, NULLAEI, aei, NULLPA, pz, pl, ode,
        !          1293:                prequirements, srequirements, ISN (srequirements), tokens, sf,
        !          1294:                udata, NACDATA, NULLQOS, acc, aci)
        !          1295:                == NOTOK) {
        !          1296:            fprintf (stderr, "failed\n");
        !          1297:            acs_adios (aca, "A-ASSOCIATE.REQUEST");
        !          1298:        }
        !          1299:        sd = acc -> acc_sd;
        !          1300: #else
        !          1301:        if ((i = AcAsynAssocRequest (ode, NULLAEI, aei, NULLPA, pz, pl, ode,
        !          1302:                prequirements, srequirements, ISN (srequirements), tokens, sf,
        !          1303:                udata, NACDATA, NULLQOS, acc, aci, 1)) == NOTOK) {
        !          1304:            fprintf (stderr, "failed\n");
        !          1305:            acs_adios (aca, "A-(ASYN-)ASSOCIATE.REQUEST");
        !          1306:        }
        !          1307:        sd = acc -> acc_sd, cc = 0;
        !          1308:        while (i == CONNECTING_1 || i == CONNECTING_2) {
        !          1309:            int     nfds;
        !          1310:            fd_set  mask,
        !          1311:                   *rmask,
        !          1312:                   *wmask;
        !          1313: 
        !          1314:            nfds = 0;
        !          1315:            FD_ZERO (&mask);
        !          1316:            if (PSelectMask (sd, &mask, &nfds, pi) == NOTOK) {
        !          1317:                fprintf (stderr, "failed\n");
        !          1318:                acs_adios (aca, "A-(ASYN-)ASSOCIATE.REQUEST(PSelectMask)");
        !          1319:            }
        !          1320:            rmask = (i == CONNECTING_2) ? &mask : NULLFD;
        !          1321:            wmask = (i == CONNECTING_2) ? NULLFD : &mask;
        !          1322: 
        !          1323:            fprintf (stderr, ".");
        !          1324:            if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
        !          1325:                fprintf (stderr, "failed\n");
        !          1326:                adios ("failed", "select");
        !          1327:            }
        !          1328: 
        !          1329:            if ((rmask && FD_ISSET (sd, rmask) == 0)
        !          1330:                    || (wmask && FD_ISSET (sd, wmask) == 0))
        !          1331:                continue;
        !          1332:            
        !          1333:            if ((i = AcAsynRetryRequest (sd, acc, aci)) == NOTOK) {
        !          1334:                fprintf (stderr, "failed\n");
        !          1335:                acs_adios (aca, "A-ASYN-RETRY.REQUEST");
        !          1336:            }
        !          1337:        }
        !          1338: #endif
        !          1339: 
        !          1340:        if (acc -> acc_result != ACS_ACCEPT) {
        !          1341:            fprintf (stderr, "failed\n");
        !          1342:            adios (NULLCP, "connection rejected: [%s], %d elements",
        !          1343:                    AcErrString (acc -> acc_result), acc -> acc_ninfo);
        !          1344:        }
        !          1345:     }
        !          1346:     else {
        !          1347: #ifndef        ASYNC
        !          1348:        if (PConnRequest (NULLPA, pz, pl, NULLOID, prequirements,
        !          1349:                srequirements, srequirements
        !          1350:                    & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY)
        !          1351:                ? (long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1)) + SERIAL_MIN
        !          1352:                : SERIAL_NONE, tokens, sf, udata, NPDATA, NULLQOS, pc, pi) == NOTOK) {
        !          1353:            fprintf (stderr, "failed\n");
        !          1354:            ps_adios (pa, "P-CONNECT.REQUEST");
        !          1355:        }
        !          1356:        sd = pc -> pc_sd;
        !          1357: #else
        !          1358:        if ((i = PAsynConnRequest (NULLPA, pz, pl, NULLOID, prequirements,
        !          1359:                srequirements, ISN (srequirements), tokens, sf, udata, NPDATA,
        !          1360:                NULLQOS, pc, pi, 1)) == NOTOK) {
        !          1361:            fprintf (stderr, "failed\n");
        !          1362:            ps_adios (pa, "P-CONNECT.REQUEST");
        !          1363:        }
        !          1364:        sd = pc -> pc_sd, cc = 0;
        !          1365:        while (i == CONNECTING_1 || i == CONNECTING_2) {
        !          1366:            int     nfds;
        !          1367:            fd_set  mask,
        !          1368:                   *rmask,
        !          1369:                   *wmask;
        !          1370: 
        !          1371:            nfds = 0;
        !          1372:            FD_ZERO (&mask);
        !          1373:            if (PSelectMask (sd, &mask, &nfds, pi) == NOTOK) {
        !          1374:                fprintf (stderr, "failed\n");
        !          1375:                ps_adios (pa, "P-CONNECT.REQUEST(PSelectMask)");
        !          1376:            }
        !          1377:            rmask = (i == CONNECTING_2) ? &mask : NULLFD;
        !          1378:            wmask = (i == CONNECTING_2) ? NULLFD : &mask;
        !          1379: 
        !          1380:            fprintf (stderr, ".");
        !          1381:            if (xselect (nfds, rmask, wmask, NULLFD, 1) == NOTOK) {
        !          1382:                fprintf (stderr, "failed\n");
        !          1383:                adios ("failed", "select");
        !          1384:            }
        !          1385: 
        !          1386:            if ((rmask && FD_ISSET (sd, rmask) == 0)
        !          1387:                    || (wmask && FD_ISSET (sd, wmask) == 0))
        !          1388:                continue;
        !          1389: 
        !          1390:            if ((i = PAsynRetryRequest (sd, pc, pi)) == NOTOK) {
        !          1391:                fprintf (stderr, "failed\n");
        !          1392:                ps_adios (pa, "P-ASYN-RETRY.REQUEST");
        !          1393:            }
        !          1394:        }
        !          1395: #endif
        !          1396: 
        !          1397:        if (pc -> pc_result != PC_ACCEPT) {
        !          1398:            fprintf (stderr, "failed\n");
        !          1399:            adios (NULLCP, "connection rejected: [%s], %d elements",
        !          1400:                    PErrString (pc -> pc_result), pc -> pc_ninfo);
        !          1401:        }
        !          1402:     }
        !          1403:     fprintf (stderr, "connected\n");
        !          1404: 
        !          1405:     if (isacs) {
        !          1406:        pc = &acc -> acc_connect;
        !          1407: 
        !          1408: #ifdef DEBUG
        !          1409:        {
        !          1410:            advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
        !          1411: 
        !          1412:            advise (NULLCP,
        !          1413:                    "responding AE title: %s, responding PSAP address: %s",
        !          1414:                    sprintaei (&acc -> acc_respondtitle),
        !          1415:                    paddr2str (&pc -> pc_responding, NULLNA));
        !          1416: 
        !          1417:            advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
        !          1418: 
        !          1419:            pl = &pc -> pc_ctxlist;
        !          1420:            for (i = 0; i < pl -> pc_nctx; i++)
        !          1421:                advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
        !          1422:                        pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
        !          1423:                        pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
        !          1424:            advise (NULLCP, "default %d", pc -> pc_defctxresult);
        !          1425:            advise (NULLCP, "p/s requirements 0x%x/0x%x",
        !          1426:                    pc -> pc_prequirements, pc -> pc_srequirements);
        !          1427:        }
        !          1428: #endif
        !          1429: 
        !          1430:        pl = &pc -> pc_ctxlist;
        !          1431: 
        !          1432:        if (mode == echo) {
        !          1433:            if (acc -> acc_ninfo != NACDATA)
        !          1434:                adios (NULLCP, "expecting %d hellos, got %d elements",
        !          1435:                        NACDATA, acc -> acc_ninfo);
        !          1436:            for (i = 0; i < NACDATA; i++) {
        !          1437:                if ((pe = acc -> acc_info[i]) == NULLPE)
        !          1438:                    adios (NULLCP, "hello %d: NULL", i);
        !          1439:                if ((j = prim2num (pe)) == NOTOK
        !          1440:                        && pe -> pe_errno != PE_ERR_NONE)
        !          1441:                    adios (NULLCP, "hello %d: %s", i,
        !          1442:                            pe_error (pe -> pe_errno));
        !          1443:                if (j != i)
        !          1444:                    adios (NULLCP, "hello %d: value %d", i, j);
        !          1445:                if (pe -> pe_context != udata[i] -> pe_context)
        !          1446:                    adios (NULLCP, "hello %d: context of %d instead of %d",
        !          1447:                        i, pe -> pe_context, udata[i] -> pe_context);
        !          1448:            }
        !          1449:        }
        !          1450: 
        !          1451:        goto do_release;
        !          1452:     }
        !          1453:     else {
        !          1454: #ifdef DEBUG
        !          1455:        {
        !          1456:            advise (NULLCP, "responding PSAP address: %s",
        !          1457:                    paddr2str (&pc -> pc_responding, NULLNA));
        !          1458: 
        !          1459:            advise (NULLCP, "greetings: %d elements", pc -> pc_ninfo);
        !          1460: 
        !          1461:            pl = &pc -> pc_ctxlist;
        !          1462:            for (i = 0; i < pl -> pc_nctx; i++)
        !          1463:                advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
        !          1464:                        pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
        !          1465:                        pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
        !          1466:            advise (NULLCP, "default %d", pc -> pc_defctxresult);
        !          1467:            advise (NULLCP, "p/s requirements 0x%x/0x%x",
        !          1468:                    pc -> pc_prequirements, pc -> pc_srequirements);
        !          1469:        }
        !          1470: #endif
        !          1471: 
        !          1472:        if (mode == echo) {
        !          1473:            if (pc -> pc_ninfo != NPDATA)
        !          1474:                adios (NULLCP, "expecting %d hellos, got %d elements",
        !          1475:                        NPDATA, pc -> pc_ninfo);
        !          1476:            for (i = 0; i < NPDATA; i++) {
        !          1477:                if ((pe = pc -> pc_info[i]) == NULLPE)
        !          1478:                    adios (NULLCP, "hello %d: NULL", i);
        !          1479:                if ((j = prim2num (pe)) == NOTOK
        !          1480:                        && pe -> pe_errno != PE_ERR_NONE)
        !          1481:                    adios (NULLCP, "hello %d: %s", i,
        !          1482:                            pe_error (pe -> pe_errno));
        !          1483:                if (j != i)
        !          1484:                    adios (NULLCP, "hello %d: value %d", i, j);
        !          1485:                if (pe -> pe_context != udata[i] -> pe_context)
        !          1486:                    adios (NULLCP, "hello %d: context of %d instead of %d",
        !          1487:                        i, pe -> pe_context, udata[i] -> pe_context);
        !          1488:            }
        !          1489:        }
        !          1490:     }
        !          1491: 
        !          1492:     nctxs = 0;
        !          1493:     pl = &pc -> pc_ctxlist;
        !          1494:     for (i = 0; i < pl -> pc_nctx; i++)
        !          1495:        if (pl -> pc_ctx[i].pc_result == PC_ACCEPT)
        !          1496:                datactxs[nctxs++] = pl -> pc_ctx[i].pc_id;
        !          1497: 
        !          1498:     srequirements = pc -> pc_srequirements;
        !          1499:     nmodes = 0;
        !          1500:     datamodes[nmodes++] = SX_NORMAL;
        !          1501:     if (srequirements & SR_EXPEDITED)
        !          1502:        datamodes[nmodes++] = SX_EXPEDITED;
        !          1503:     if ((srequirements & SR_CAPABILITY) && (srequirements & SR_ACTIVITY))
        !          1504:        datamodes[nmodes++] = SX_CAPDIND;
        !          1505:     if (srequirements & SR_TYPEDATA)
        !          1506:        datamodes[nmodes++] = SX_TYPED;
        !          1507: 
        !          1508: #define dotoken(requires,shift,bit,type) \
        !          1509: { \
        !          1510:     if (srequirements & requires) \
        !          1511:        switch (pc -> pc_settings & (ST_MASK << shift)) { \
        !          1512:            case ST_CALL_VALUE: \
        !          1513:                adios (NULLCP, "%s token: choice", type); \
        !          1514:  \
        !          1515:            case ST_INIT_VALUE: \
        !          1516:                owned |= bit, avail |= bit; \
        !          1517:                break; \
        !          1518:  \
        !          1519:            case ST_RESP_VALUE: \
        !          1520:                avail |= bit; \
        !          1521:                break; \
        !          1522:  \
        !          1523:            default: \
        !          1524:                adios (NULLCP, "%s token: reserved", type); \
        !          1525:        } \
        !          1526: }
        !          1527:        dotokens ();
        !          1528: #undef dotoken
        !          1529: 
        !          1530:     if (isacs)
        !          1531:        ACCFREE (acc)
        !          1532:     else
        !          1533:        PCFREE (pc);
        !          1534: 
        !          1535:     if (srequirements & SR_ACTIVITY) {
        !          1536:        (void) strcpy (id -> sd_data, mode == echo ? "echo" : "sink");
        !          1537:        id -> sd_len = strlen (id -> sd_data);
        !          1538:        if (PActStartRequest (sd, id, udata, NPDATA, pi) == NOTOK)
        !          1539:            ps_adios (pa, "P-ACTIVITY-START.REQUEST");
        !          1540:     }
        !          1541: 
        !          1542:     if (fstat (fileno (stdin), &st) != NOTOK
        !          1543:            && (st.st_mode & S_IFMT) == S_IFREG
        !          1544:            && (cc = st.st_size) != 0) {
        !          1545:        (void) lseek (fileno (stdin), 0L, 0);
        !          1546: 
        !          1547:        if ((cp = malloc ((unsigned) cc)) == NULL)
        !          1548:            adios (NULLCP, "no memory");
        !          1549:        for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !          1550:            switch (i = read (fileno (stdin), dp, j)) {
        !          1551:                case NOTOK:
        !          1552:                    adios ("on stdin", "read failed");
        !          1553: 
        !          1554:                case OK:
        !          1555:                    adios (NULLCP, "premature end-of-file");
        !          1556:                    
        !          1557:                default:
        !          1558:                    break;
        !          1559:            }
        !          1560:        if ((pe = oct2prim (cp, cc)) == NULLPE)
        !          1561:            adios (NULLCP, "unable to allocate PSDU");
        !          1562:        free (cp);
        !          1563:        if (nctxs)
        !          1564:            pe -> pe_context = datactxs[0];
        !          1565:        for (i = 10; i > 0; i--) {
        !          1566: #ifdef TIMER
        !          1567:            timer (0);
        !          1568: #endif
        !          1569:            ps_datarequest (sd, pe, SX_NORMAL, 0);
        !          1570: #ifdef TIMER
        !          1571:            timer (cc);
        !          1572: #endif
        !          1573:        }
        !          1574:        pe_free (pe);
        !          1575:     }
        !          1576:     else {
        !          1577:        for (j = l = m = 0; fgets (buffer, sizeof buffer, stdin); ) {
        !          1578:            k = j >= nmodes ? SX_EXPEDITED : datamodes[j++ % nmodes];
        !          1579:            if ((cc = strlen (buffer) + 1) > SX_EXSIZE - 7
        !          1580:                    && k == SX_EXPEDITED) {
        !          1581:                if ((k = datamodes[j++ % nmodes]) == SX_EXPEDITED)
        !          1582:                    k = datamodes[j++ % nmodes];
        !          1583:            }
        !          1584: 
        !          1585:            switch (k) {
        !          1586:                case SX_CAPDIND:
        !          1587:                    if (!(requirements & SR_RESYNC) || l++ & 0x01) {
        !          1588:                        ps_waitfor (sd, ST_ACT_TOKEN);
        !          1589:                        if (l & 0x03) {
        !          1590:                            if (PActIntrRequest (sd, SP_SEQUENCE, pi)
        !          1591:                                    == NOTOK)
        !          1592:                                ps_adios (pa, "P-ACTIVITY-INTERRUPT.REQUEST");
        !          1593:                        }
        !          1594:                        else {
        !          1595:                            if (PActDiscRequest (sd, SP_SEQUENCE, pi)
        !          1596:                                    == NOTOK)
        !          1597:                                ps_adios (pa, "P-ACTIVITY-DISCARD.REQUEST");
        !          1598:                        }
        !          1599:                        ps_waitfor (sd, -1);
        !          1600:                        goto push_data;
        !          1601:                    }
        !          1602:                    tokens = 0;
        !          1603: #define dotoken(requires,shift,bit,type) \
        !          1604: { \
        !          1605:                    if (requirements & requires) \
        !          1606:                        tokens |= ST_CALL_VALUE << shift; \
        !          1607: }
        !          1608:                    dotokens ();
        !          1609: #undef dotoken
        !          1610:                    if (PReSyncRequest (sd, SYNC_SET, ssn - 1, tokens,
        !          1611:                                udata, NPDATA, pi) == NOTOK)
        !          1612:                        ps_adios (pa, "P-RESYNCHRONIZE.REQUEST");
        !          1613:                    ps_waitfor (sd, -1);
        !          1614:                    break;
        !          1615: 
        !          1616:                case SX_EXPEDITED:
        !          1617:                    if (j >= nmodes)
        !          1618:                        j = j % nmodes;
        !          1619:                    if (!(srequirements & SR_EXPEDITED))
        !          1620:                        k = SX_NORMAL;  /* fall... */
        !          1621:                default:
        !          1622: push_data: ;
        !          1623:                    if ((pe = oct2prim (buffer, cc)) == NULLPE)
        !          1624:                        adios (NULLCP, "unable to allocate PSDU");
        !          1625:                    if (nctxs && k != SX_EXPEDITED)
        !          1626:                        pe -> pe_context = datactxs[m++ % nctxs];
        !          1627:                    ps_datarequest (sd, pe, k, 1);
        !          1628:                    pe_free (pe);
        !          1629:                    if (k == SX_CAPDIND
        !          1630:                            && PActResumeRequest (sd, id, id, 
        !          1631:                                    (long) (getpid () % (SERIAL_MAX - SERIAL_MIN + 1))
        !          1632:                                    + SERIAL_MIN, sf, udata, NPDATA, pi)
        !          1633:                                    == NOTOK)
        !          1634:                        ps_adios (pa, "P-ACTIVITY-RESUME.REQUEST");
        !          1635:                    break;
        !          1636:            }
        !          1637:        }
        !          1638: 
        !          1639:        if (requirements & SR_EXCEPTIONS) {
        !          1640:            if (owned & ST_DAT_TOKEN)
        !          1641:                if (PGTokenRequest (sd, ST_DAT_TOKEN, pi) == NOTOK)
        !          1642:                    ps_adios (pa, "P-TOKEN-GIVE.REQUEST");
        !          1643:                else
        !          1644:                    owned &= ~ST_DAT_TOKEN;
        !          1645:            if (PUReportRequest (sd, SP_NOREASON, udata, NPDATA, pi) == NOTOK)
        !          1646:                ps_adios (pa, "P-U-EXCEPTION-REPORT.REQUEST");
        !          1647:            ps_waitfor (sd, -1);
        !          1648:        }    
        !          1649:     }
        !          1650: 
        !          1651:     if ((requirements & SR_MAJORSYNC) && !(requirements & SR_ACTIVITY)) {
        !          1652:        if (PMajSyncRequest (sd, &ssn, udata, NPDATA, pi) == NOTOK)
        !          1653:            switch (pa -> pa_reason) {
        !          1654:                case PC_OPERATION:
        !          1655:                    ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
        !          1656:                            | ST_MAJ_TOKEN);
        !          1657:                    if (PMajSyncRequest (sd, &ssn, udata, NPDATA, pi) == OK)
        !          1658:                        break;  /* else fall */
        !          1659: 
        !          1660:                default:
        !          1661:                    ps_adios (pa, "P-MAJOR-SYNC.REQUEST");
        !          1662:            }
        !          1663: 
        !          1664:        ps_waitfor (sd, -1);
        !          1665:     }
        !          1666: 
        !          1667:     if (requirements & SR_ACTIVITY) {
        !          1668:        if (PActEndRequest (sd, &ssn, udata, NPDATA, pi) == NOTOK)
        !          1669:            switch (pa -> pa_reason) {
        !          1670:                case PC_OPERATION:
        !          1671:                    ps_waitfor (sd, avail);
        !          1672:                    if (PActEndRequest (sd, &ssn, udata, NPDATA, pi) == OK)
        !          1673:                        break;  /* else fall */
        !          1674: 
        !          1675:                default:
        !          1676:                    ps_adios (pa, "P-ACTIVITY-END.REQUEST");
        !          1677:            }
        !          1678: 
        !          1679:        ps_waitfor (sd, -1);
        !          1680:                
        !          1681:        if (PGControlRequest (sd, pi) == NOTOK)
        !          1682:            switch (pa -> pa_reason) {
        !          1683:                case PC_OPERATION:
        !          1684:                    ps_waitfor (sd, avail);
        !          1685:                    if (PGControlRequest (sd, pi) == OK)
        !          1686:                        break;  /* else fall */
        !          1687: 
        !          1688:                default:
        !          1689:                    ps_adios (pa, "P-CONTROL-GIVE.REQUEST");
        !          1690:            }
        !          1691: 
        !          1692:        owned = 0;
        !          1693: 
        !          1694:        ps_waitfor (sd, -1);
        !          1695:     }
        !          1696: 
        !          1697: do_release: ;
        !          1698:     if (isacs) {
        !          1699:        if (AcRelRequest (sd, ACF_NORMAL, udata, NACDATA, NOTOK, acr, aci)
        !          1700:                == NOTOK)
        !          1701:            switch (aca -> aca_reason) {
        !          1702:                case ACS_OPERATION:
        !          1703:                    ps_waitfor (sd, avail);
        !          1704:                    if (AcRelRequest (sd, ACF_NORMAL, udata, NACDATA, NOTOK,
        !          1705:                                      acr, aci) == OK)
        !          1706:                        break;  /* else fall */
        !          1707: 
        !          1708:                default:
        !          1709:                    acs_adios (aca, "A-RELEASE.REQUEST");
        !          1710:        }
        !          1711: 
        !          1712:        if (!acr -> acr_affirmative) {
        !          1713:            (void) AcUAbortRequest (sd, NULLPEP, 0, aci);
        !          1714:            adios (NULLCP, "release rejected by peer: %d, %d elements",
        !          1715:                        acr -> acr_reason, acr -> acr_ninfo);
        !          1716:        }
        !          1717: 
        !          1718: #ifdef DEBUG
        !          1719:        advise (NULLCP, "A-RELEASE.CONFIRMATION: %d, %d elements",
        !          1720:                acr -> acr_reason, acr -> acr_ninfo);
        !          1721: #endif         
        !          1722:        ACRFREE (acr);
        !          1723:     }
        !          1724:     else {
        !          1725:        if (PRelRequest (sd, udata, NPDATA, NOTOK, pr, pi) == NOTOK)
        !          1726:            switch (pa -> pa_reason) {
        !          1727:                case PC_OPERATION: 
        !          1728:                case PC_WAITING: 
        !          1729:                    ps_waitfor (sd, avail);
        !          1730:                    if (PRelRequest (sd, udata, NPDATA, NOTOK, pr, pi) == OK)
        !          1731:                        break;  /* else fall */
        !          1732: 
        !          1733:                default: 
        !          1734:                    ps_adios (pa, "P-RELEASE.REQUEST");
        !          1735:            }
        !          1736: 
        !          1737:        if (!pr -> pr_affirmative) {
        !          1738:            (void) PUAbortRequest (sd, NULLPEP, 0, pi);
        !          1739:            adios (NULLCP, "release rejected by peer: %d elements",
        !          1740:                    pr -> pr_ninfo);
        !          1741:        }
        !          1742:        PRFREE (pr);
        !          1743:     }
        !          1744: 
        !          1745:     for (i = 0; i < NPDATA; i++)
        !          1746:        pe_free (udata[i]);
        !          1747: }
        !          1748: 
        !          1749: /*  */
        !          1750: 
        !          1751: static int ps_datarequest (sd, pe, dm, sync)
        !          1752: int    sd;
        !          1753: PE     pe;
        !          1754: int    dm,
        !          1755:        sync;
        !          1756: {
        !          1757:     int     result;
        !          1758:     struct PSAPdata pxs;
        !          1759:     register struct PSAPdata   *px = &pxs;
        !          1760:     struct PSAPindication   pis;
        !          1761:     register struct PSAPindication *pi = &pis;
        !          1762:     register struct PSAPabort  *pa = &pi -> pi_abort;
        !          1763: 
        !          1764:     switch (dm) {
        !          1765:        default: 
        !          1766:            if (PDataRequest (sd, &pe, 1, pi) == NOTOK)
        !          1767:                switch (pa -> pa_reason) {
        !          1768:                    case PC_OPERATION: 
        !          1769:                        ps_waitfor (sd, ST_DAT_TOKEN);
        !          1770:                        if (PDataRequest (sd, &pe, 1, pi) == OK)
        !          1771:                            break;/* else fall */
        !          1772: 
        !          1773:                    default: 
        !          1774:                        ps_adios (pa, "P-DATA.REQUEST");
        !          1775:                }
        !          1776:            break;
        !          1777: 
        !          1778:        case SX_EXPEDITED: 
        !          1779:            if (PExpdRequest (sd, &pe, 1, pi) == NOTOK)
        !          1780:                ps_adios (pa, "P-EXPEDITED-DATA.REQUEST");
        !          1781:            break;
        !          1782: 
        !          1783:        case SX_CAPDIND: 
        !          1784:            if (PCapdRequest (sd, &pe, 1, pi) == NOTOK)
        !          1785:                switch (pa -> pa_reason) {
        !          1786:                    case PC_OPERATION: 
        !          1787:                        ps_waitfor (sd, avail & ~ST_RLS_TOKEN);
        !          1788:                        if (PCapdRequest (sd, &pe, 1, pi) == OK)
        !          1789:                            break;/* else fall */
        !          1790: 
        !          1791:                    default: 
        !          1792:                        ps_adios (pa, "P-CAPABILITY-DATA.REQUEST");
        !          1793:                }
        !          1794:            break;
        !          1795: 
        !          1796:        case SX_TYPED: 
        !          1797:            if (PTypedRequest (sd, &pe, 1, pi) == NOTOK)
        !          1798:                ps_adios (pa, "P-TYPED-DATA.REQUEST");
        !          1799:            break;
        !          1800:     }
        !          1801: 
        !          1802:     if (mode == echo || dm == SX_CAPDIND)
        !          1803:        for (;;) {
        !          1804:            switch (result = PReadRequest (sd, px, NOTOK, pi)) {
        !          1805:                case NOTOK: 
        !          1806:                    ps_adios (pa, "P-READ.REQUEST");
        !          1807: 
        !          1808:                case OK: 
        !          1809:                    if ((dm != SX_CAPDIND ? dm : SX_CAPDCNF)
        !          1810:                            != px -> px_type) {
        !          1811:                        advise (NULLCP,
        !          1812:                                "data indication type mismatch, orig=%d echo=%d",
        !          1813:                                dm, px -> px_type);
        !          1814:                        status++;
        !          1815:                    }
        !          1816:                    if (px -> px_ninfo != 1) {
        !          1817:                        advise (NULLCP, "length mismatch, orig=%d echo=%d",
        !          1818:                                1, px -> px_ninfo);
        !          1819:                        status++;
        !          1820:                    }
        !          1821:                    if (pe -> pe_context != (*px -> px_info) -> pe_context) {
        !          1822:                        advise (NULLCP, "context mismatch, orig=%d echo=%d",
        !          1823:                                pe -> pe_context,
        !          1824:                                (*px -> px_info) -> pe_context);
        !          1825:                        status++;
        !          1826:                    }
        !          1827:                    if (pe_cmp (pe, *px -> px_info)) {
        !          1828:                        advise (NULLCP, "data mismatch");
        !          1829:                        status++;
        !          1830:                    }
        !          1831:                    PXFREE (px)
        !          1832:                    break;
        !          1833: 
        !          1834:                case DONE: 
        !          1835:                    ps_event (sd, pi);
        !          1836:                    continue;
        !          1837: 
        !          1838:                default: 
        !          1839:                    adios (NULLCP, "unknown return from PReadRequest=%d",
        !          1840:                            result);
        !          1841:            }
        !          1842:            break;
        !          1843:        }
        !          1844: 
        !          1845:     if (sync &&
        !          1846:            (srequirements & SR_MINORSYNC) && !(srequirements & SR_ACTIVITY)) {
        !          1847:        if (PMinSyncRequest (sd, SYNC_CONFIRM, &ssn, NULLPEP, 0, pi) == NOTOK)
        !          1848:            switch (pa -> pa_reason) {
        !          1849:                case PC_OPERATION: 
        !          1850:                    ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN);
        !          1851:                    if (PMinSyncRequest (sd, SYNC_CONFIRM, &ssn, NULLPEP, 0,
        !          1852:                            pi) == OK)
        !          1853:                        break;  /* else fall */
        !          1854: 
        !          1855:                default: 
        !          1856:                    ps_adios (pa, "P-MINOR-SYNC.REQUEST");
        !          1857:            }
        !          1858: 
        !          1859:        ps_waitfor (sd, -1);
        !          1860:     }
        !          1861:     else
        !          1862:        if (sync
        !          1863:                && (srequirements & SR_ACTIVITY)
        !          1864:                && (srequirements & SR_MAJORSYNC)
        !          1865:                && dm == SX_NORMAL) {
        !          1866:            if (PMajSyncRequest (sd, &ssn, NULLPEP, 0, pi) == NOTOK)
        !          1867:                switch (pa -> pa_reason) {
        !          1868:                    case PC_OPERATION: 
        !          1869:                        ps_waitfor (sd, ST_DAT_TOKEN | ST_MIN_TOKEN
        !          1870:                                | ST_MAJ_TOKEN);
        !          1871:                        if (PMajSyncRequest (sd, &ssn, NULLPEP, 0, pi) == OK)
        !          1872:                            break;/* else fall */
        !          1873: 
        !          1874:                    default: 
        !          1875:                        ps_adios (pa, "P-MAJOR-SYNC.REQUEST");
        !          1876:                }
        !          1877: 
        !          1878:            ps_waitfor (sd, -1);
        !          1879:        }
        !          1880: }
        !          1881: 
        !          1882: /*  */
        !          1883: 
        !          1884: static int  ps_waitfor (sd, want)
        !          1885: int    sd,
        !          1886:        want;
        !          1887: {
        !          1888:     int     result,
        !          1889:            tokens;
        !          1890:     struct PSAPdata pxs;
        !          1891:     register struct PSAPdata   *px = &pxs;
        !          1892:     struct PSAPindication   pis;
        !          1893:     register struct PSAPindication *pi = &pis;
        !          1894:     register struct PSAPabort  *pa = &pi -> pi_abort;
        !          1895: 
        !          1896:     for (;;) {
        !          1897:        if (want == -1) {
        !          1898:            want = avail;
        !          1899:            goto read_it;
        !          1900:        }
        !          1901: 
        !          1902:        tokens = 0;
        !          1903: #define dotoken(requires,shift,bit,type) \
        !          1904: { \
        !          1905:        if ((want & bit) && !(owned & bit)) \
        !          1906:            tokens |= bit; \
        !          1907: }
        !          1908:        dotokens ();
        !          1909: #undef dotoken
        !          1910:        if (tokens == 0)
        !          1911:            return;
        !          1912: 
        !          1913:        if (PPTokenRequest (sd, tokens, NULLPEP, 0, pi) == NOTOK)
        !          1914:            ps_adios (pa, "P-TOKEN-PLEASE.REQUEST");
        !          1915: 
        !          1916: read_it: ;
        !          1917:        switch (result = PReadRequest (sd, px, NOTOK, pi)) {
        !          1918:            case NOTOK: 
        !          1919:                ps_adios (pa, "P-READ.REQUEST");
        !          1920: 
        !          1921:            case OK: 
        !          1922:                ps_abort (sd, "protocol screw-up");
        !          1923: 
        !          1924:            case DONE: 
        !          1925:                ps_event (sd, pi);
        !          1926:                break;
        !          1927: 
        !          1928:            default: 
        !          1929:                adios (NULLCP, "unknown return from PReadRequest=%d",
        !          1930:                        result);
        !          1931:        }
        !          1932:     }
        !          1933: }
        !          1934: 
        !          1935: /*  */
        !          1936: 
        !          1937: static ps_event (sd, pi)
        !          1938: int    sd;
        !          1939: register struct PSAPindication *pi;
        !          1940: {
        !          1941:     register struct PSAPabort  *pa = &pi -> pi_abort;
        !          1942:     register struct PSAPactivity  *pv = &pi -> pi_activity;
        !          1943:     register struct PSAPfinish  *pf = &pi -> pi_finish;
        !          1944:     register struct PSAPreport  *pp = &pi -> pi_report;
        !          1945:     register struct PSAPsync   *pn = &pi -> pi_sync;
        !          1946:     register struct PSAPtoken  *pt = &pi -> pi_token;
        !          1947:     struct AcSAPindication  acis;
        !          1948:     register struct AcSAPindication *aci = &acis;
        !          1949:     register struct AcSAPabort *aca = &aci -> aci_abort;
        !          1950:     register struct AcSAPfinish *acf = &aci -> aci_finish;
        !          1951: 
        !          1952:     switch (pi -> pi_type) {
        !          1953:        case PI_TOKEN: 
        !          1954:            switch (pt -> pt_type) {
        !          1955:                case ST_GIVE: 
        !          1956:                case ST_CONTROL: 
        !          1957:                    owned = pt -> pt_owned;
        !          1958:                    break;
        !          1959: 
        !          1960:                case ST_PLEASE: 
        !          1961:                    if (PGTokenRequest (sd,
        !          1962:                                (int) pt -> pt_tokens, pi)
        !          1963:                            == NOTOK)
        !          1964:                        ps_adios (pa, "P-TOKEN-GIVE.REQUEST");
        !          1965:                    else
        !          1966:                        owned &= ~pt -> pt_tokens;
        !          1967:                    break;
        !          1968: 
        !          1969:                default: 
        !          1970:                    adios (NULLCP,
        !          1971:                            "unknown token indication type=0x%x",
        !          1972:                            pt -> pt_type);
        !          1973:            }
        !          1974:            PTFREE (pt);
        !          1975:            break;
        !          1976: 
        !          1977:        case PI_SYNC: 
        !          1978:            switch (pn -> pn_type) {
        !          1979:                case SN_MAJORIND: 
        !          1980:                    adios (NULLCP, "majorsync indication %d",
        !          1981:                            pn -> pn_ssn);
        !          1982:                    break;
        !          1983: 
        !          1984:                case SN_MAJORCNF: 
        !          1985:                    break;
        !          1986: 
        !          1987:                case SN_MINORIND: 
        !          1988:                    adios (NULLCP, "minorsync indication %d%s",
        !          1989:                            pn -> pn_ssn, pn -> pn_options == SYNC_CONFIRM
        !          1990:                            ? " (wants confirmation)" : NULLCP);
        !          1991:                    break;
        !          1992: 
        !          1993:                case SN_MINORCNF: 
        !          1994:                    break;
        !          1995: 
        !          1996:                case SN_RESETIND: 
        !          1997: #define        dotoken(requires,shift,bit,type) \
        !          1998: { \
        !          1999:                    if (srequirements & requires) \
        !          2000:                        switch (pn -> pn_settings & (ST_MASK << shift)) { \
        !          2001:                            case ST_CALL_VALUE << shift: \
        !          2002:                                pn -> pn_settings &= ~(ST_MASK << shift); \
        !          2003:                                pn -> pn_settings |= ST_RESP_VALUE << shift; \
        !          2004:                            case ST_RESP_VALUE << shift: \
        !          2005:                                owned &= ~bit; \
        !          2006:                                break; \
        !          2007:  \
        !          2008:                            case ST_INIT_VALUE << shift: \
        !          2009:                                owned |= bit; \
        !          2010:                                break; \
        !          2011:  \
        !          2012:                            default: \
        !          2013:                                adios (NULLCP, "%s token: reserved", type); \
        !          2014:                                break; \
        !          2015:                        } \
        !          2016: }
        !          2017:                    dotokens ();
        !          2018: #undef dotoken
        !          2019:                    if (PReSyncResponse (sd, pn -> pn_ssn, pn -> pn_settings,
        !          2020:                                NULLPEP, 0, pi) == NOTOK)
        !          2021:                        ps_adios (pa, "P-RESYNCHRONIZE.RESPONSE");
        !          2022:                    break;
        !          2023: 
        !          2024:                case SN_RESETCNF: 
        !          2025:                    break;
        !          2026: 
        !          2027:                default: 
        !          2028:                    adios (NULLCP, "unknown sync indication=0x%x, ssn=%d",
        !          2029:                            pn -> pn_type, pn -> pn_ssn);
        !          2030:            }
        !          2031:            PNFREE (pn);
        !          2032:            break;
        !          2033: 
        !          2034:        case PI_ACTIVITY: 
        !          2035:            switch (pv -> pv_type) {
        !          2036:                case SV_START: 
        !          2037:                    adios (NULLCP, "activity start indication: %*.*s",
        !          2038:                            pv -> pv_id.sd_len, pv -> pv_id.sd_len,
        !          2039:                            pv -> pv_id.sd_data);
        !          2040: 
        !          2041:                case SV_RESUME: 
        !          2042:                    adios (NULLCP, 
        !          2043:                            "activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d",
        !          2044:                            pv -> pv_id.sd_len, pv -> pv_id.sd_len,
        !          2045:                            pv -> pv_id.sd_data, pv -> pv_oid.sd_len,
        !          2046:                            pv -> pv_oid.sd_len, pv -> pv_oid.sd_data,
        !          2047:                            sprintref (&pv -> pv_connect), pv -> pv_ssn);
        !          2048: 
        !          2049:                case SV_INTRIND: 
        !          2050:                    adios (NULLCP, "activity interrupt indication %d",
        !          2051:                            pv -> pv_reason);
        !          2052: 
        !          2053:                case SV_INTRCNF: 
        !          2054:                    break;
        !          2055: 
        !          2056:                case SV_DISCIND: 
        !          2057:                    adios (NULLCP, "activity discard indication %d",
        !          2058:                            pv -> pv_reason);
        !          2059: 
        !          2060:                case SV_DISCCNF: 
        !          2061:                    break;
        !          2062: 
        !          2063:                case SV_ENDIND: 
        !          2064:                    adios (NULLCP, "activity end indication %d",
        !          2065:                            pv -> pv_ssn);
        !          2066: 
        !          2067:                case SV_ENDCNF: 
        !          2068:                    break;
        !          2069: 
        !          2070:                default: 
        !          2071:                    adios (NULLCP, "unknown activity indication=0x%x",
        !          2072:                            pv -> pv_type);
        !          2073:            }
        !          2074:            PVFREE (pv);
        !          2075:            break;
        !          2076: 
        !          2077:        case PI_REPORT: 
        !          2078:            advise (NULLCP, "%s report %d",
        !          2079:                    pp -> pp_peer ? "user" : "provider", pp -> pp_reason);
        !          2080:            if (srequirements & SR_DAT_EXISTS) {
        !          2081:                if (PGTokenRequest (sd, ST_DAT_TOKEN, pi) == NOTOK)
        !          2082:                    ps_adios (pa, "P-TOKEN-GIVE.REQUEST (to clear exception)");
        !          2083:                else
        !          2084:                    owned &= ~ST_DAT_TOKEN;
        !          2085:            }
        !          2086:            else
        !          2087:                ps_abort (sd, "aborted");
        !          2088:            PPFREE (pp);
        !          2089:            break;
        !          2090: 
        !          2091:        case PI_FINISH: 
        !          2092:            if (isacs) {
        !          2093:                if (AcFINISHser (sd, pf, aci) == NOTOK)
        !          2094:                    acs_adios (aca, "AcFINISHser");
        !          2095: #ifdef DEBUG
        !          2096:                advise (NULLCP, "A-RELEASE.INDICATION %d, %d elements",
        !          2097:                        acf -> acf_reason, acf -> acf_ninfo);
        !          2098:                if (AcRelResponse (sd, ACS_USER_NOREASON, ACR_NOTFINISHED,
        !          2099:                                NULLPEP, 0, aci) == NOTOK)
        !          2100:                    acs_adios (aca, "A-RELEASE.RESPONSE");
        !          2101: #endif
        !          2102: 
        !          2103:                ACFFREE (acf);
        !          2104:            }
        !          2105:            else {
        !          2106:                if (PRelResponse (sd, PC_REJECTED, NULLPEP, 0, pi) == NOTOK)
        !          2107:                    ps_adios (pa, "P-RELEASE.RESPONSE");
        !          2108: 
        !          2109:                PFFREE (pf);
        !          2110:            }
        !          2111:            break;
        !          2112: 
        !          2113:        default: 
        !          2114:            adios (NULLCP, "unknown indication type=0x%x", pi -> pi_type);
        !          2115:     }
        !          2116: }
        !          2117: 
        !          2118: /*  */
        !          2119: 
        !          2120: static  ps_abort (sd, reason)
        !          2121: int     sd;
        !          2122: char   *reason;
        !          2123: {
        !          2124:     struct PSAPindication   pis;
        !          2125:     register struct PSAPindication *pi = &pis;
        !          2126:     register struct PSAPabort  *pa = &pi -> pi_abort;
        !          2127:     struct AcSAPindication  acis;
        !          2128:     register struct AcSAPindication *aci = &acis;
        !          2129:     register struct AcSAPabort *aca = &aci -> aci_abort;
        !          2130: 
        !          2131:     if (isacs) {
        !          2132:        if (AcUAbortRequest (sd, NULLPEP, 0, aci) == NOTOK)
        !          2133:            acs_adios (aca, "A-U-ABORT.REQUEST");
        !          2134:     }
        !          2135:     else {
        !          2136:        if (PUAbortRequest (sd, NULLPEP, 0, pi) == NOTOK)
        !          2137:            ps_adios (pa, "P-U-ABORT.REQUEST");
        !          2138:     }
        !          2139: 
        !          2140:     adios (NULLCP, "%s", reason);
        !          2141: }
        !          2142: 
        !          2143: /*  */
        !          2144: 
        !          2145: static void  ps_adios (pa, event)
        !          2146: register struct PSAPabort *pa;
        !          2147: char   *event;
        !          2148: {
        !          2149:     ps_advise (pa, event);
        !          2150: 
        !          2151:     _exit (1);
        !          2152: }
        !          2153: 
        !          2154: 
        !          2155: static void  ps_advise (pa, event)
        !          2156: register struct PSAPabort *pa;
        !          2157: char   *event;
        !          2158: {
        !          2159:     char    buffer[BUFSIZ];
        !          2160: 
        !          2161:     if (pa -> pa_cc > 0)
        !          2162:        (void) sprintf (buffer, "[%s] %*.*s",
        !          2163:                PErrString (pa -> pa_reason),
        !          2164:                pa -> pa_cc, pa -> pa_cc, pa -> pa_data);
        !          2165:     else
        !          2166:        (void) sprintf (buffer, "[%s]", PErrString (pa -> pa_reason));
        !          2167: 
        !          2168:     advise (NULLCP, "%s: %s%s", event, buffer,
        !          2169:            pa -> pa_peer ? " (peer initiated)" : "");
        !          2170: }
        !          2171: 
        !          2172: /*    AcSAP */
        !          2173: 
        !          2174: static void  acs_adios (aca, event)
        !          2175: register struct AcSAPabort *aca;
        !          2176: char   *event;
        !          2177: {
        !          2178:     acs_advise (aca, event);
        !          2179: 
        !          2180:     _exit (1);
        !          2181: }
        !          2182: 
        !          2183: 
        !          2184: static void  acs_advise (aca, event)
        !          2185: register struct AcSAPabort *aca;
        !          2186: char   *event;
        !          2187: {
        !          2188:     char    buffer[BUFSIZ];
        !          2189: 
        !          2190:     if (aca -> aca_cc > 0)
        !          2191:        (void) sprintf (buffer, "[%s] %*.*s",
        !          2192:                AcErrString (aca -> aca_reason),
        !          2193:                aca -> aca_cc, aca -> aca_cc, aca -> aca_data);
        !          2194:     else
        !          2195:        (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason));
        !          2196: 
        !          2197:        advise (NULLCP, "%s: %s (source %d)", event, buffer,
        !          2198:                aca -> aca_source);
        !          2199: }
        !          2200: 
        !          2201: /*    RtSAP */
        !          2202: 
        !          2203: static int turn = 0;
        !          2204: 
        !          2205: /*  */
        !          2206: 
        !          2207: static int  rts_main (is, addr)
        !          2208: struct isoservent *is;
        !          2209: char *addr;
        !          2210: {
        !          2211:     int     sd,
        !          2212:             cc,
        !          2213:             i,
        !          2214:             j,
        !          2215:            ros;
        !          2216:     char   *cp,
        !          2217:            *dp,
        !          2218:             buffer[BUFSIZ];
        !          2219:     register struct PSAPaddr   *pa;
        !          2220:     struct PSAPctxlist pls;
        !          2221:     register struct PSAPctxlist *pl = &pls;
        !          2222:     struct AcSAPrelease acrs;
        !          2223:     register struct AcSAPrelease *acr = &acrs;
        !          2224:     struct RtSAPaddr    rtzs;
        !          2225:     register struct RtSAPaddr  *rtz = &rtzs;
        !          2226:     struct RtSAPconnect rtcs;
        !          2227:     register struct RtSAPconnect   *rtc = &rtcs;
        !          2228:     struct RtSAPindication  rtis;
        !          2229:     register struct RtSAPindication *rti = &rtis;
        !          2230:     register struct RtSAPabort   *rta = &rti -> rti_abort;
        !          2231: #ifdef DEBUG
        !          2232:     struct AcSAPconnect *acc= &rtc -> rtc_connect;
        !          2233:     struct PSAPconnect *pc = &acc -> acc_connect;
        !          2234: #endif
        !          2235:     register PE            pe;
        !          2236:     AEI            aei;
        !          2237:     OID            oid,
        !          2238:            ode;
        !          2239:     struct stat st;
        !          2240: 
        !          2241:     if ((pe = int2prim (i = getpid ())) == NULLPE)
        !          2242:        adios (NULLCP, "unable to allocate hello");
        !          2243: 
        !          2244:     turn = mode == sink;
        !          2245: 
        !          2246:     if (isacs) {
        !          2247:        if (ros = strncmp (isacs, "isode/ros_", strlen ("isode/ros_")) == 0)
        !          2248:            mode = strcmp (isacs, "isode/ros_sink") ? echo : sink;
        !          2249:        else
        !          2250:            mode = strcmp (isacs, "isode/rtse sink") ? echo : sink;
        !          2251:        turn = mode == sink;
        !          2252: 
        !          2253:        if ((aei = str2aei (addr, isacs)) == NULLAEI)
        !          2254:            adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
        !          2255:        if ((pa = aei2addr (aei)) == NULLPA)
        !          2256:            adios (NULLCP, "address translation failed");
        !          2257: 
        !          2258:        cp = mode == echo ? "isode echo pci" : "isode sink pci";
        !          2259:        if ((ode = ode2oid (cp)) == NULLOID)
        !          2260:            adios (NULLCP, "%s: unknown object descriptor", cp);
        !          2261:        ode = oid_cpy (ode);
        !          2262: 
        !          2263:        for (j = (pl -> pc_nctx = NPCTX - 2) - 1; j >= 0; j--) {
        !          2264:            pl -> pc_ctx[j].pc_id = j * 2 + 1;
        !          2265:            if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
        !          2266:                adios (NULLCP, "iso asn.1 abstract syntax: unknown");
        !          2267:            pl -> pc_ctx[j].pc_asn = oid_cpy (oid);
        !          2268:            pl -> pc_ctx[j].pc_atn = NULLOID;
        !          2269:        }
        !          2270: 
        !          2271:        fprintf (stderr, "%s... ", addr);
        !          2272:        (void) fflush (stderr);
        !          2273:        if (RtOpenRequest (RTS_TWA, turn ? RTS_INITIATOR : RTS_RESPONDER,
        !          2274:                    ode, NULLAEI, aei, NULLPA, pa, pl, ode, pe,
        !          2275:                    NULLQOS, rtc, rti) == NOTOK) {
        !          2276:            fprintf (stderr, "failed\n");
        !          2277:            rts_adios (rta, "RT-OPEN.REQUEST");
        !          2278:        }
        !          2279:     }
        !          2280:     else {
        !          2281:        register struct SSAPaddr *sa;
        !          2282: 
        !          2283:        if (ros = strncmp (is -> is_entity, "ros_", strlen ("ros_")) == 0) {
        !          2284:            mode = strcmp (is -> is_entity, "ros_sink") ? echo : sink;
        !          2285:            turn = mode == sink;
        !          2286:        }
        !          2287: 
        !          2288:        rtz -> rta_port = is -> is_port;        /* yikes! */
        !          2289:        if ((is = getisoserventbyname ("rts", "ssap")) == NULL)
        !          2290:            adios (NULLCP, "ssap/rts: unknown entity");
        !          2291:        if ((sa = is2saddr (addr, NULLCP, is)) == NULLSA)
        !          2292:            adios (NULLCP, "address translation failed");
        !          2293:        rtz -> rta_addr = *sa;  /* struct copy */
        !          2294: 
        !          2295:        fprintf (stderr, "%s... ", addr);
        !          2296:        (void) fflush (stderr);
        !          2297:        if (RtBeginRequest (rtz, RTS_TWA, turn ? RTS_INITIATOR : RTS_RESPONDER,
        !          2298:                    pe, rtc, rti) == NOTOK) {
        !          2299:            fprintf (stderr, "failed\n");
        !          2300:            rts_adios (rta, "RT-BEGIN.REQUEST");
        !          2301:        }
        !          2302:     }
        !          2303: 
        !          2304:     pe_free (pe);
        !          2305: 
        !          2306:     if (rtc -> rtc_result != RTS_ACCEPT) {
        !          2307:        fprintf (stderr, "failed\n");
        !          2308:        adios (NULLCP, "association rejected: [%s]",
        !          2309:                RtErrString (rtc -> rtc_result));
        !          2310:     }
        !          2311:     fprintf (stderr, "connected\n");
        !          2312: 
        !          2313: #ifdef DEBUG
        !          2314:     advise (NULLCP, "sent greetings of %d", i);
        !          2315: #endif
        !          2316: 
        !          2317:     sd = rtc -> rtc_sd;
        !          2318:     if (rtc -> rtc_data) {
        !          2319:        if ((i = prim2num (rtc -> rtc_data)) == NOTOK
        !          2320:                && rtc -> rtc_data -> pe_errno != PE_ERR_NONE)
        !          2321:            adios (NULLCP, "error decoding hello: %s (%d)",
        !          2322:                    pe_error (rtc -> rtc_data -> pe_errno), i);
        !          2323: #ifdef DEBUG
        !          2324:        advise (NULLCP, "received greetings of %d", i);
        !          2325: #endif
        !          2326:     }
        !          2327: 
        !          2328: #ifdef DEBUG
        !          2329:     if (isacs) {
        !          2330:            advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
        !          2331: 
        !          2332:            advise (NULLCP,
        !          2333:                    "responding AE title: %s, responding PSAP address: %s",
        !          2334:                    sprintaei (&acc -> acc_respondtitle),
        !          2335:                    paddr2str (&pc -> pc_responding, NULLNA));
        !          2336: 
        !          2337:            advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
        !          2338: 
        !          2339:            pl = &pc -> pc_ctxlist;
        !          2340:            for (i = 0; i < pl -> pc_nctx; i++)
        !          2341:                advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
        !          2342:                        pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
        !          2343:                        pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
        !          2344:            advise (NULLCP, "default %d", pc -> pc_defctxresult);
        !          2345:            advise (NULLCP, "p/s requirements 0x%x/0x%x",
        !          2346:                    pc -> pc_prequirements, pc -> pc_srequirements);
        !          2347:        }
        !          2348: #endif
        !          2349: 
        !          2350:     RTCFREE (rtc);
        !          2351: 
        !          2352:     if (ros) {
        !          2353:        struct RoSAPindication rois;
        !          2354:        register struct RoSAPpreject *rop = &rois.roi_preject;
        !          2355: 
        !          2356:        if (RoSetService (sd, RoRtService, &rois) == NOTOK)
        !          2357:            ros_adios (rop, "set RO/PT fails");
        !          2358: 
        !          2359:        do_ros (sd);
        !          2360:        return;
        !          2361:     }
        !          2362: 
        !          2363:     if (fstat (fileno (stdin), &st) != NOTOK
        !          2364:            && (st.st_mode & S_IFMT) == S_IFREG
        !          2365:            && (cc = st.st_size) != 0) {
        !          2366:        (void) lseek (fileno (stdin), 0L, 0);
        !          2367: 
        !          2368:        if ((cp = malloc ((unsigned) cc)) == NULL)
        !          2369:            adios (NULLCP, "no memory");
        !          2370:        for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !          2371:            switch (i = read (fileno (stdin), dp, j)) {
        !          2372:                case NOTOK: 
        !          2373:                    adios ("on stdin", "read failed");
        !          2374: 
        !          2375:                case OK: 
        !          2376:                    adios (NULLCP, "premature end-of-file");
        !          2377: 
        !          2378:                default: 
        !          2379:                    break;
        !          2380:            }
        !          2381:        if ((pe = oct2prim (cp, cc)) == NULLPE)
        !          2382:            adios (NULLCP, "unable to allocate APDU");
        !          2383:        free (cp);
        !          2384:        for (i = 10; i > 0; i--) {
        !          2385: #ifdef TIMER
        !          2386:            timer (0);
        !          2387: #endif
        !          2388:            rts_transferequest (sd, pe);
        !          2389: #ifdef TIMER
        !          2390:            timer (cc);
        !          2391: #endif
        !          2392:        }
        !          2393:        pe_free (pe);
        !          2394:     }
        !          2395:     else
        !          2396:        while (fgets (buffer, sizeof buffer, stdin)) {
        !          2397:            if ((pe = oct2prim (buffer, strlen (buffer) + 1)) == NULLPE)
        !          2398:                adios (NULLCP, "unable to allocate APDU");
        !          2399:            rts_transferequest (sd, pe);
        !          2400:            pe_free (pe);
        !          2401:        }
        !          2402: 
        !          2403:     if (isacs) {
        !          2404:        if ((pe = int2prim (i = getpid ())) == NULLPE)
        !          2405:            adios (NULLCP, "unable to allocate hello");
        !          2406: 
        !          2407:        if (RtCloseRequest (sd, ACF_NORMAL, pe, acr, rti) == NOTOK)
        !          2408:            switch (rta -> rta_reason) {
        !          2409:                case RTS_OPERATION: 
        !          2410:                case RTS_WAITING: 
        !          2411:                    rts_waitfor (sd);
        !          2412:                    if (RtCloseRequest (sd, ACF_NORMAL, pe, acr, rti)
        !          2413:                            == OK)
        !          2414:                        break;  /* else fall */
        !          2415: 
        !          2416:                default: 
        !          2417:                    rts_adios (rta, "RT-CLOSE.REQUEST");
        !          2418:            }
        !          2419: 
        !          2420:        if (!acr -> acr_affirmative) {
        !          2421:            (void) RtUAbortRequest (sd, NULLPE, rti);
        !          2422:            adios (NULLCP, "release rejected by peer: %d, %d elements",
        !          2423:                        acr -> acr_reason, acr -> acr_ninfo);
        !          2424:        }
        !          2425: 
        !          2426:        if (mode == echo) {
        !          2427:            if (acr -> acr_ninfo != 1)
        !          2428:                advise (NULLCP, "got %d elements returned on close",
        !          2429:                            acr -> acr_ninfo);
        !          2430:                if (pe_cmp (pe, acr -> acr_info[0])) {
        !          2431:                    advise (NULLCP, "data mismatch");
        !          2432:                    status++;
        !          2433:                }
        !          2434:        }
        !          2435: 
        !          2436:        ACRFREE (acr);
        !          2437: 
        !          2438:        pe_free (pe);
        !          2439:     }
        !          2440:     else
        !          2441:        if (RtEndRequest (sd, rti) == NOTOK)
        !          2442:            switch (rta -> rta_reason) {
        !          2443:                case RTS_OPERATION: 
        !          2444:                case RTS_WAITING: 
        !          2445:                    rts_waitfor (sd);
        !          2446:                    if (RtEndRequest (sd, rti) == OK)
        !          2447:                        break;  /* else fall */
        !          2448: 
        !          2449:                default: 
        !          2450:                    rts_adios (rta, "RT-END.REQUEST");
        !          2451:            }
        !          2452: }
        !          2453: 
        !          2454: /*  */
        !          2455: 
        !          2456: static int  rts_transferequest (sd, pe)
        !          2457: int    sd;
        !          2458: register PE    pe;
        !          2459: {
        !          2460:     int     result;
        !          2461:     struct RtSAPindication  rtis;
        !          2462:     register struct RtSAPindication *rti = &rtis;
        !          2463:     register struct RtSAPabort *rta = &rti -> rti_abort;
        !          2464:     register struct RtSAPtransfer  *rtt = &rti -> rti_transfer;
        !          2465: 
        !          2466:     if (RtTransferRequest (sd, pe, NOTOK, rti) == NOTOK)
        !          2467:        switch (rta -> rta_reason) {
        !          2468:            case RTS_OPERATION: 
        !          2469:                rts_waitfor (sd);
        !          2470:                if (RtTransferRequest (sd, pe, NOTOK, rti) == OK)
        !          2471:                    break;      /* else fall */
        !          2472: 
        !          2473:            default: 
        !          2474:                if (RTS_FATAL (rta -> rta_reason))
        !          2475:                    rts_adios (rta, "RT-TRANSFER.REQUEST");
        !          2476:                rts_advise (rta, "RT-TRANSFER.REQUEST");
        !          2477:                return;
        !          2478:        }
        !          2479: 
        !          2480:     if (mode == echo)
        !          2481:        for (;;)
        !          2482:            switch (result = RtWaitRequest (sd, NOTOK, rti)) {
        !          2483:                case NOTOK: 
        !          2484:                    rts_adios (rta, "RT-WAIT.REQUEST");
        !          2485: 
        !          2486:                case OK: 
        !          2487:                    if (pe_cmp (pe, rtt -> rtt_data)) {
        !          2488:                        advise (NULLCP, "data mismatch");
        !          2489:                        status++;
        !          2490:                    }
        !          2491:                    RTTFREE (rtt);
        !          2492:                    return;
        !          2493: 
        !          2494:                case DONE: 
        !          2495:                    rts_event (sd, rti);
        !          2496:                    break;
        !          2497: 
        !          2498:                default: 
        !          2499:                    adios (NULLCP, "unknown return from RtWaitRequest=%d",
        !          2500:                            result);
        !          2501:            }
        !          2502: }
        !          2503: 
        !          2504: /*  */
        !          2505: 
        !          2506: static int  rts_waitfor (sd)
        !          2507: int    sd;
        !          2508: {
        !          2509:     int     result;
        !          2510:     struct RtSAPindication  rtis;
        !          2511:     register struct RtSAPindication *rti = &rtis;
        !          2512:     register struct RtSAPabort *rta = &rti -> rti_abort;
        !          2513:     static int  priority = 1;
        !          2514: 
        !          2515:     if (turn)
        !          2516:        return;
        !          2517: 
        !          2518:     if (RtPTurnRequest (sd, priority++, rti) == NOTOK)
        !          2519:        rts_adios (rta, "RT-TURN-PLEASE.REQUEST");
        !          2520: 
        !          2521:     while (!turn)
        !          2522:        switch (result = RtWaitRequest (sd, NOTOK, rti)) {
        !          2523:            case NOTOK: 
        !          2524:                rts_adios (rta, "RT-WAIT.REQUEST");
        !          2525: 
        !          2526:            case OK: 
        !          2527:                adios (NULLCP, "protocol screw-up");
        !          2528: 
        !          2529:            case DONE: 
        !          2530:                rts_event (sd, rti);
        !          2531:                break;
        !          2532: 
        !          2533:            default: 
        !          2534:                adios (NULLCP, "unknown return from RtWaitRequest=%d",
        !          2535:                        result);
        !          2536:        }
        !          2537: }
        !          2538: 
        !          2539: /*  */
        !          2540: 
        !          2541: static int  rts_event (sd, rti)
        !          2542: int    sd;
        !          2543: register struct RtSAPindication *rti;
        !          2544: {
        !          2545:     register struct RtSAPabort *rta = &rti -> rti_abort;
        !          2546:     register struct RtSAPturn  *rtu = &rti -> rti_turn;
        !          2547: 
        !          2548:     switch (rti -> rti_type) {
        !          2549:        case RTI_TURN: 
        !          2550:            if (rtu -> rtu_please) {
        !          2551:                if (RtGTurnRequest (sd, rti) == NOTOK)
        !          2552:                    rts_adios (rta, "RT-TURN-GIVE.REQUEST");
        !          2553:                turn = 0;
        !          2554:            }
        !          2555:            else
        !          2556:                turn = 1;
        !          2557:            break;
        !          2558: 
        !          2559:        case RTI_CLOSE: 
        !          2560:            adios (NULLCP, "got RT-END.INDICATION");
        !          2561: 
        !          2562:        case RTI_FINISH:
        !          2563:            adios (NULLCP, "got RT-CLOSE.INDICATION");
        !          2564: 
        !          2565:        default: 
        !          2566:            adios (NULLCP, "unknown indication type=0x%x",
        !          2567:                    rti -> rti_type);
        !          2568:     }
        !          2569: }
        !          2570: 
        !          2571: /*  */
        !          2572: 
        !          2573: static void  rts_adios (rta, event)
        !          2574: register struct RtSAPabort *rta;
        !          2575: char   *event;
        !          2576: {
        !          2577:     rts_advise (rta, event);
        !          2578: 
        !          2579:     _exit (1);
        !          2580: }
        !          2581: 
        !          2582: 
        !          2583: static void  rts_advise (rta, event)
        !          2584: register struct RtSAPabort *rta;
        !          2585: char   *event;
        !          2586: {
        !          2587:     char    buffer[BUFSIZ];
        !          2588: 
        !          2589:     if (rta -> rta_cc > 0)
        !          2590:        (void) sprintf (buffer, "[%s] %*.*s", RtErrString (rta -> rta_reason),
        !          2591:                rta -> rta_cc, rta -> rta_cc, rta -> rta_data);
        !          2592:     else
        !          2593:        (void) sprintf (buffer, "[%s]", RtErrString (rta -> rta_reason));
        !          2594: 
        !          2595:     advise (NULLCP, "%s: %s", event, buffer);
        !          2596: }
        !          2597: 
        !          2598: /*    RoSAP */
        !          2599: 
        !          2600: static int  ros_main (is, addr)
        !          2601: struct isoservent *is;
        !          2602: char *addr;
        !          2603: {
        !          2604:     int     sd,
        !          2605:             i;
        !          2606:     char   *cp;
        !          2607:     struct SSAPref  sfs;
        !          2608:     register struct SSAPref *sf;
        !          2609:     register struct PSAPaddr   *pa;
        !          2610:     struct AcSAPconnect accs;
        !          2611:     register struct AcSAPconnect   *acc = &accs;
        !          2612:     struct AcSAPindication  acis;
        !          2613:     register struct AcSAPindication *aci = &acis;
        !          2614:     register struct AcSAPabort *aca = &aci -> aci_abort;
        !          2615:     struct RoSAPaddr    roas;
        !          2616:     register struct RoSAPaddr  *roa = &roas;
        !          2617:     struct RoSAPconnect rocs;
        !          2618:     register struct RoSAPconnect   *roc = &rocs;
        !          2619:     struct RoSAPindication  rois;
        !          2620:     register struct RoSAPindication *roi = &rois;
        !          2621:     register struct RoSAPpreject   *rop = &roi -> roi_preject;
        !          2622: #ifdef DEBUG
        !          2623:     struct PSAPconnect *pc = &acc -> acc_connect;
        !          2624: #endif
        !          2625:     struct PSAPctxlist pls;
        !          2626:     register struct PSAPctxlist *pl = &pls;
        !          2627:     AEI            aei;
        !          2628:     OID     oid,
        !          2629:            ode;
        !          2630:     register PE            pe;
        !          2631: 
        !          2632:     if (isacs) {
        !          2633:        if ((aei = str2aei (addr, isacs)) == NULLAEI)
        !          2634:            adios (NULLCP, "%s-%s: unknown application-entity", addr, isacs);
        !          2635:        if ((pa = aei2addr (aei)) == NULLPA)
        !          2636:            adios (NULLCP, "address translation failed");
        !          2637: 
        !          2638:        cp = mode == echo ? "isode echo pci" : "isode sink pci";
        !          2639:        if ((ode = ode2oid (cp)) == NULLOID)
        !          2640:            adios (NULLCP, "%s: unknown object descriptor", cp);
        !          2641:        ode = oid_cpy (ode);
        !          2642: 
        !          2643:        if ((sf = addr2ref (PLocalHostName ())) == NULL) {
        !          2644:            sf = &sfs;
        !          2645:            (void) bzero ((char *) sf, sizeof *sf);
        !          2646:        }
        !          2647:        pl -> pc_nctx = 1;
        !          2648:        pl -> pc_ctx[0].pc_id = 1;
        !          2649:        if ((oid = ode2oid ("iso asn.1 abstract syntax")) == NULLOID)
        !          2650:            adios (NULLCP, "iso asn.1 abstract syntax: unknown");
        !          2651:        pl -> pc_ctx[0].pc_asn = oid_cpy (oid);
        !          2652:        pl -> pc_ctx[0].pc_atn = NULLOID;
        !          2653: 
        !          2654:        fprintf (stderr, "%s... ", addr);
        !          2655:        (void) fflush (stderr);
        !          2656:        if (AcAssocRequest (ode, NULLAEI, aei, NULLPA, pa, pl, ode,
        !          2657:                    0, ROS_MYREQUIRE, SERIAL_NONE, 0, sf, NULLPEP, 0, NULLQOS,
        !          2658:                    acc, aci)
        !          2659:                == NOTOK)
        !          2660:            acs_adios (aca, "A-ASSOCIATE.REQUEST");
        !          2661: 
        !          2662:        if (acc -> acc_result != ACS_ACCEPT) {
        !          2663:            fprintf (stderr, "failed\n");
        !          2664:            adios (NULLCP, "association rejected: [%s]",
        !          2665:                    AcErrString (acc -> acc_result));
        !          2666:        }
        !          2667:        fprintf (stderr, "connected\n");
        !          2668: 
        !          2669:        sd = acc -> acc_sd;
        !          2670: 
        !          2671: #ifdef DEBUG
        !          2672:        pa = &pc -> pc_responding;
        !          2673:        {
        !          2674:            advise (NULLCP, "context: %s", oid2ode (acc -> acc_context));
        !          2675: 
        !          2676:            advise (NULLCP,
        !          2677:                    "responding AE title: %s, responding PSAP address: %s",
        !          2678:                    sprintaei (&acc -> acc_respondtitle),
        !          2679:                    paddr2str (&pc -> pc_responding, NULLNA));
        !          2680: 
        !          2681:            advise (NULLCP, "greetings: %d elements", acc -> acc_ninfo);
        !          2682: 
        !          2683:            pl = &pc -> pc_ctxlist;
        !          2684:            for (i = 0; i < pl -> pc_nctx; i++)
        !          2685:                advise (NULLCP, "ctx %d: 0x%x 0x%x %d",
        !          2686:                        pl -> pc_ctx[i].pc_id, pl -> pc_ctx[i].pc_asn,
        !          2687:                        pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result);
        !          2688:            advise (NULLCP, "default %d", pc -> pc_defctxresult);
        !          2689:            advise (NULLCP, "p/s requirements 0x%x/0x%x",
        !          2690:                    pc -> pc_prequirements, pc -> pc_srequirements);
        !          2691:        }
        !          2692: #endif
        !          2693: 
        !          2694:        ACCFREE (acc);
        !          2695: 
        !          2696:        if (RoSetService (sd, RoPService, roi) == NOTOK)
        !          2697:            ros_adios (rop, "set RO/PT fails");
        !          2698:     }
        !          2699:     else {
        !          2700:        register struct SSAPaddr *sa;
        !          2701: 
        !          2702:        roa -> roa_port = is -> is_port;        /* yikes! */
        !          2703:        if ((is = getisoserventbyname ("ros", "ssap")) == NULL)
        !          2704:            adios (NULLCP, "ssap/ros: unknown entity");
        !          2705:        if ((sa = is2saddr (addr, NULLCP, is)) == NULLSA)
        !          2706:            adios (NULLCP, "address translation failed");
        !          2707:        roa -> roa_addr = *sa;  /* struct copy */
        !          2708: 
        !          2709:        if ((pe = int2prim (i = getpid ())) == NULLPE)
        !          2710:            adios (NULLCP, "unable to allocate hello");
        !          2711: 
        !          2712:        fprintf (stderr, "%s... ", addr);
        !          2713:        (void) fflush (stderr);
        !          2714:        if (RoBeginRequest (roa, pe, roc, roi) == NOTOK) {
        !          2715:            fprintf (stderr, "failed\n");
        !          2716:            ros_adios (rop, "RO-BEGIN.REQUEST");
        !          2717:        }
        !          2718: 
        !          2719:        pe_free (pe);
        !          2720: 
        !          2721:        if (roc -> roc_result != ROS_ACCEPT) {
        !          2722:            fprintf (stderr, "failed\n");
        !          2723:            adios (NULLCP, "association rejected: [%s]",
        !          2724:                    RoErrString (roc -> roc_result));
        !          2725:        }
        !          2726:        fprintf (stderr, "connected\n");
        !          2727: 
        !          2728: #ifdef DEBUG
        !          2729:        advise (NULLCP, "sent greetings of %d", i);
        !          2730: #endif
        !          2731: 
        !          2732:        sd = roc -> roc_sd;
        !          2733:        if (roc -> roc_data) {
        !          2734:            if ((i = prim2num (roc -> roc_data)) == NOTOK
        !          2735:                    && roc -> roc_data -> pe_errno != PE_ERR_NONE)
        !          2736:                adios (NULLCP, "error decoding hello: %s (%d)",
        !          2737:                        pe_error (roc -> roc_data -> pe_errno), i);
        !          2738: #ifdef DEBUG
        !          2739:            advise (NULLCP, "received greetings of %d", i);
        !          2740: #endif
        !          2741:        }
        !          2742:        ROCFREE (roc);
        !          2743:     }
        !          2744: 
        !          2745:     do_ros (sd);
        !          2746: }
        !          2747: 
        !          2748: /*  */
        !          2749: 
        !          2750: static int  do_ros (sd)
        !          2751: int    sd;
        !          2752: {
        !          2753:     int     cc,
        !          2754:             i,
        !          2755:             j;
        !          2756:     char   *cp,
        !          2757:            *dp,
        !          2758:             buffer[BUFSIZ];
        !          2759:     struct RoSAPindication  rois;
        !          2760:     register struct RoSAPindication *roi = &rois;
        !          2761:     register struct RoSAPpreject   *rop = &roi -> roi_preject;
        !          2762:     struct AcSAPrelease acrs;
        !          2763:     register struct AcSAPrelease *acr = &acrs;
        !          2764:     register PE        pe;
        !          2765:     struct stat st;
        !          2766:     
        !          2767:     if (fstat (fileno (stdin), &st) != NOTOK
        !          2768:            && (st.st_mode & S_IFMT) == S_IFREG
        !          2769:            && (cc = st.st_size) != 0) {
        !          2770:        (void) lseek (fileno (stdin), 0L, 0);
        !          2771: 
        !          2772:        if ((cp = malloc ((unsigned) cc)) == NULL)
        !          2773:            adios (NULLCP, "no memory");
        !          2774:        for (dp = cp, j = cc; j > 0; dp += i, j -= i)
        !          2775:            switch (i = read (fileno (stdin), dp, j)) {
        !          2776:                case NOTOK: 
        !          2777:                    adios ("on stdin", "read failed");
        !          2778: 
        !          2779:                case OK: 
        !          2780:                    adios (NULLCP, "premature end-of-file");
        !          2781: 
        !          2782:                default: 
        !          2783:                    break;
        !          2784:            }
        !          2785:        if ((pe = oct2prim (cp, cc)) == NULLPE)
        !          2786:            adios (NULLCP, "unable to allocate invocation argument");
        !          2787:        free (cp);
        !          2788:        for (i = 10; i > 0; i--) {
        !          2789: #ifdef TIMER
        !          2790:            timer (0);
        !          2791: #endif
        !          2792:            ros_invokerequest (sd, pe);
        !          2793: #ifdef TIMER
        !          2794:            timer (cc);
        !          2795: #endif
        !          2796:        }
        !          2797:        pe_free (pe);
        !          2798:     }
        !          2799:     else
        !          2800:        while (fgets (buffer, sizeof buffer, stdin)) {
        !          2801:            if ((pe = oct2prim (buffer, strlen (buffer) + 1)) == NULLPE)
        !          2802:                adios (NULLCP, "unable to allocate invocation argument");
        !          2803:            ros_invokerequest (sd, pe);
        !          2804:            pe_free (pe);
        !          2805:        }
        !          2806: 
        !          2807:     if (isrts) {
        !          2808:        struct RtSAPindication  rtis;
        !          2809:        register struct RtSAPindication *rti = &rtis;
        !          2810:        register struct RtSAPabort *rta = &rti -> rti_abort;
        !          2811: 
        !          2812:        if (isacs) {
        !          2813:            if (RtCloseRequest (sd, ACF_NORMAL, NULLPE, acr, rti) == NOTOK)
        !          2814:                switch (rta -> rta_reason) {
        !          2815:                    case RTS_OPERATION:
        !          2816:                    case RTS_WAITING: 
        !          2817:                        rts_waitfor (sd);
        !          2818:                        if (RtCloseRequest (sd, ACF_NORMAL, NULLPE, acr, rti)
        !          2819:                                == OK)
        !          2820:                            break;      /* else fall */
        !          2821: 
        !          2822:                    default:
        !          2823:                        rts_adios (rta, "RT-CLOSE.REQUEST");
        !          2824:                }
        !          2825: 
        !          2826:            if (!acr -> acr_affirmative) {
        !          2827:                (void) RtUAbortRequest (sd, NULLPE, rti);
        !          2828:                adios (NULLCP, "release rejected by peer: %d, %d elements",
        !          2829:                            acr -> acr_reason, acr -> acr_ninfo);
        !          2830:            }
        !          2831:        }
        !          2832:        else
        !          2833:            if (RtEndRequest (sd, rti) == NOTOK)
        !          2834:                switch (rta -> rta_reason) {
        !          2835:                    case RTS_OPERATION: 
        !          2836:                    case RTS_WAITING: 
        !          2837:                        rts_waitfor (sd);
        !          2838:                        if (RtEndRequest (sd, rti) == OK)
        !          2839:                            break;      /* else fall */
        !          2840: 
        !          2841:                    default: 
        !          2842:                        rts_adios (rta, "RT-END.REQUEST");
        !          2843:                }
        !          2844:     }
        !          2845:     else
        !          2846:        if (isacs) {
        !          2847:            struct AcSAPindication  acis;
        !          2848:            register struct AcSAPindication *aci = &acis;
        !          2849:            register struct AcSAPabort *aca = &aci -> aci_abort;
        !          2850: 
        !          2851:            if (AcRelRequest (sd, ACF_NORMAL, NULLPEP, 0, NOTOK, acr, aci)
        !          2852:                    == NOTOK)
        !          2853:                acs_adios (aca, "A-RELEASE.REQUEST");
        !          2854: 
        !          2855:            if (!acr -> acr_affirmative) {
        !          2856:                (void) AcUAbortRequest (sd, NULLPEP, 0, aci);
        !          2857:                adios (NULLCP, "release rejected by peer: %d, %d elements",
        !          2858:                            acr -> acr_reason, acr -> acr_ninfo);
        !          2859:            }
        !          2860:            ACRFREE (acr);
        !          2861:        }
        !          2862:        else
        !          2863:            if (RoEndRequest (sd, ROS_NOPRIO, roi) == NOTOK)
        !          2864:                ros_adios (rop, "RO-END.REQUEST");
        !          2865: }
        !          2866: 
        !          2867: /*  */
        !          2868: 
        !          2869: static int  ros_invokerequest (sd, pe)
        !          2870: int    sd;
        !          2871: PE     pe;
        !          2872: {
        !          2873:     int     result;
        !          2874:     struct RoSAPindication  rois;
        !          2875:     register struct RoSAPindication *roi = &rois;
        !          2876:     register struct RoSAPpreject   *rop = &roi -> roi_preject;
        !          2877:     static int  id = 0;
        !          2878:     static int  op = 0;
        !          2879: 
        !          2880:     switch (result = RoInvokeRequest (sd, op++, ROS_SYNC, pe, ++id, NULLIP,
        !          2881:                ROS_NOPRIO, roi)) {
        !          2882:        case NOTOK: 
        !          2883:            if (ROS_FATAL (rop -> rop_reason))
        !          2884:                ros_adios (rop, "RO-INVOKE.REQUEST");
        !          2885:            ros_advise (rop, "RO-INVOKE.REQUEST");
        !          2886:            break;
        !          2887: 
        !          2888:        case OK: 
        !          2889:            switch (roi -> roi_type) {
        !          2890:                case ROI_INVOKE: 
        !          2891:                    adios (NULLCP, "got RO-INVOKE.INDICATION");
        !          2892: 
        !          2893:                case ROI_RESULT: 
        !          2894:                    {
        !          2895:                        register struct RoSAPresult *ror = &roi -> roi_result;
        !          2896: 
        !          2897:                        if (ror -> ror_id != id) {
        !          2898:                            advise (NULLCP, "id mismatch (wanted %d, got %d)",
        !          2899:                                    id, ror -> ror_id);
        !          2900:                            status++;
        !          2901:                            if (RoURejectRequest (sd, &ror -> ror_id,
        !          2902:                                    ROS_RRP_UNRECOG, ROS_NOPRIO, roi) == NOTOK)
        !          2903:                                ros_adios (rop, "RO-REJECT-U.REQUEST");
        !          2904:                        }
        !          2905:                        else
        !          2906:                            if (mode == echo
        !          2907:                                    && pe_cmp (pe, ror -> ror_result)) {
        !          2908:                                advise (NULLCP, "data mismatch");
        !          2909:                                status++;
        !          2910:                            }
        !          2911: 
        !          2912:                        RORFREE (ror);
        !          2913:                    }
        !          2914:                    break;
        !          2915: 
        !          2916:                case ROI_ERROR: 
        !          2917:                    {
        !          2918:                        register struct RoSAPerror *roe = &roi -> roi_error;
        !          2919: 
        !          2920:                        if (roe -> roe_id != id) {
        !          2921:                            advise (NULLCP, "id mismatch (wanted %d, got %d)",
        !          2922:                                    id, roe -> roe_id);
        !          2923:                            status++;
        !          2924:                            if (RoURejectRequest (sd, &roe -> roe_id,
        !          2925:                                    ROS_REP_UNRECOG, ROS_NOPRIO, roi) == NOTOK)
        !          2926:                                ros_adios (rop, "RO-REJECT-U.REQUEST");
        !          2927:                        }
        !          2928:                        else
        !          2929:                            if (mode == echo
        !          2930:                                    && pe_cmp (pe, roe -> roe_param)) {
        !          2931:                                advise (NULLCP, "data mismatch");
        !          2932:                                status++;
        !          2933:                            }
        !          2934: 
        !          2935:                        ROEFREE (roe);
        !          2936:                    }
        !          2937:                    break;
        !          2938: 
        !          2939:                case ROI_UREJECT: 
        !          2940:                    {
        !          2941:                        register struct RoSAPureject *rou = &roi -> roi_ureject;
        !          2942: 
        !          2943:                        if (rou -> rou_noid)
        !          2944:                            advise (NULLCP, "RO-REJECT-U.INDICATION: %s",
        !          2945:                                    RoErrString (rou -> rou_reason));
        !          2946:                        else
        !          2947:                            advise (NULLCP, "RO-REJECT-U.INDICATION: %s (id=%d)",
        !          2948:                                    RoErrString (rou -> rou_reason),
        !          2949:                                    rou -> rou_id);
        !          2950:                        if (!rou -> rou_noid && rou -> rou_id != id) {
        !          2951:                            advise (NULLCP, "id mismatch (wanted %d, got %d)",
        !          2952:                                    id, rou -> rou_id);
        !          2953:                            status++;
        !          2954:                        }
        !          2955:                    }
        !          2956:                    break;
        !          2957: 
        !          2958:                default: 
        !          2959:                    adios (NULLCP, "unknown indication type=%d",
        !          2960:                            roi -> roi_type);
        !          2961:            }
        !          2962:            if (isrts)
        !          2963:                turn = 0;
        !          2964:            break;
        !          2965: 
        !          2966:        case DONE: 
        !          2967:            adios (NULLCP, "got RO-END.INDICATION");
        !          2968: 
        !          2969:        default: 
        !          2970:            adios (NULLCP, "unknown return from RoInvokeRequest=%d", result);
        !          2971:     }
        !          2972: }
        !          2973: 
        !          2974: 
        !          2975: /*  */
        !          2976: 
        !          2977: static void  ros_adios (rop, event)
        !          2978: register struct RoSAPpreject *rop;
        !          2979: char   *event;
        !          2980: {
        !          2981:     ros_advise (rop, event);
        !          2982: 
        !          2983:     _exit (1);
        !          2984: }
        !          2985: 
        !          2986: 
        !          2987: static void  ros_advise (rop, event)
        !          2988: register struct RoSAPpreject *rop;
        !          2989: char   *event;
        !          2990: {
        !          2991:     char    buffer[BUFSIZ];
        !          2992: 
        !          2993:     if (rop -> rop_cc > 0)
        !          2994:        (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason),
        !          2995:                rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
        !          2996:     else
        !          2997:        (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason));
        !          2998: 
        !          2999:     advise (NULLCP, "%s: %s", event, buffer);
        !          3000: }
        !          3001: 
        !          3002: /*    TIMER */
        !          3003: 
        !          3004: #ifdef TIMER
        !          3005: 
        !          3006: #ifndef        NBBY
        !          3007: #define        NBBY    8
        !          3008: #endif
        !          3009: 
        !          3010: 
        !          3011: #ifndef        TMS
        !          3012: static  timer (cc)
        !          3013: int     cc;
        !          3014: {
        !          3015:     int     bytes;
        !          3016:     long    ms;
        !          3017:     float   bs;
        !          3018:     struct timeval  stop,
        !          3019:                     td;
        !          3020:     static struct timeval   start;
        !          3021: 
        !          3022:     if (cc == 0) {
        !          3023:        (void) gettimeofday (&start, (struct timezone *) 0);
        !          3024:        return;
        !          3025:     }
        !          3026:     else
        !          3027:        (void) gettimeofday (&stop, (struct timezone  *) 0);
        !          3028: 
        !          3029:     tvsub (&td, &stop, &start);
        !          3030:     ms = (td.tv_sec * 1000) + (td.tv_usec / 1000);
        !          3031:     bytes = mode == echo ? cc * 2 : cc;
        !          3032:     bs = (((float) bytes * NBBY * 1000) / (float) (ms ? ms : 1)) / NBBY;
        !          3033: 
        !          3034:     advise (NULLCP, "%d bytes %s in %d.%02d seconds (%.2f Kbytes/s)",
        !          3035:            cc, mode == echo ? "echoed" : "sunk",
        !          3036:            td.tv_sec, td.tv_usec / 10000, bs / 1024);
        !          3037: }
        !          3038: 
        !          3039: 
        !          3040: static  tvsub (tdiff, t1, t0)
        !          3041: register struct timeval *tdiff,
        !          3042:                        *t1,
        !          3043:                        *t0;
        !          3044: {
        !          3045: 
        !          3046:     tdiff -> tv_sec = t1 -> tv_sec - t0 -> tv_sec;
        !          3047:     tdiff -> tv_usec = t1 -> tv_usec - t0 -> tv_usec;
        !          3048:     if (tdiff -> tv_usec < 0)
        !          3049:        tdiff -> tv_sec--, tdiff -> tv_usec += 1000000;
        !          3050: }
        !          3051: #else
        !          3052: long   times ();
        !          3053: 
        !          3054: 
        !          3055: static timer (cc)
        !          3056: int    cc;
        !          3057: {
        !          3058:     int            bytes;
        !          3059:     long    ms;
        !          3060:     float   bs;
        !          3061:     long    stop,
        !          3062:            td,
        !          3063:            secs,
        !          3064:            msecs;
        !          3065:     struct tms tm;
        !          3066:     static long start;
        !          3067: 
        !          3068:     if (cc == 0) {
        !          3069:        start = times (&tm);
        !          3070:        return;
        !          3071:     }
        !          3072:     else
        !          3073:        stop = times (&tm);
        !          3074: 
        !          3075:     td = stop - start;
        !          3076:     secs = td / 60, msecs = (td % 60) * 1000 / 60;
        !          3077:     ms = (secs * 1000) +  msecs;
        !          3078:     bytes = mode == echo ? cc * 2 : cc;
        !          3079:     bs = (((float) bytes * NBBY * 1000) / (float) (ms ? ms : 1)) / NBBY;
        !          3080:     
        !          3081:     advise (NULLCP, "%d bytes %s in %d.%02d seconds (%.2f KBytes/s)",
        !          3082:            cc, mode == echo ? "echoed" : "sunk",
        !          3083:            secs, msecs / 10, bs / 1024);
        !          3084: }
        !          3085: #endif
        !          3086: #endif
        !          3087: 
        !          3088: /*    QBUF */
        !          3089: 
        !          3090: static int  qcmp (b, qb, l)
        !          3091: register char *b;
        !          3092: register struct qbuf *qb;
        !          3093: register int l;
        !          3094: {
        !          3095:     register struct qbuf   *qp;
        !          3096: 
        !          3097:     for (qp = qb -> qb_forw; qp != qb; qp = qp -> qb_forw) {
        !          3098:        if ((l -= qp -> qb_len) < 0) {
        !          3099:            advise (NULLCP, "length mismatch(1)");
        !          3100:            return NOTOK;
        !          3101:        }
        !          3102: 
        !          3103:        if (bcmp (b, qp -> qb_data, qp -> qb_len)) {
        !          3104:            advise (NULLCP, "data mismatch");
        !          3105:            return NOTOK;
        !          3106:        }
        !          3107: 
        !          3108:        b += qp -> qb_len;
        !          3109:     }
        !          3110: 
        !          3111:     if (l != 0) {
        !          3112:        advise (NULLCP, "length mismatch(2)");
        !          3113:        return NOTOK;
        !          3114:     }
        !          3115: 
        !          3116:     return OK;
        !          3117: }
        !          3118: 
        !          3119: /*    ERRORS */
        !          3120: 
        !          3121: #ifndef        lint
        !          3122: void   _advise ();
        !          3123: 
        !          3124: 
        !          3125: void   adios (va_alist)
        !          3126: va_dcl
        !          3127: {
        !          3128:     va_list ap;
        !          3129: 
        !          3130:     va_start (ap);
        !          3131: 
        !          3132:     _advise (ap);
        !          3133: 
        !          3134:     va_end (ap);
        !          3135: 
        !          3136:     _exit (1);
        !          3137: }
        !          3138: #else
        !          3139: /* VARARGS */
        !          3140: 
        !          3141: void   adios (what, fmt)
        !          3142: char   *what,
        !          3143:        *fmt;
        !          3144: {
        !          3145:     adios (what, fmt);
        !          3146: }
        !          3147: #endif
        !          3148: 
        !          3149: 
        !          3150: #ifndef        lint
        !          3151: void   advise (va_alist)
        !          3152: va_dcl
        !          3153: {
        !          3154:     va_list ap;
        !          3155: 
        !          3156:     va_start (ap);
        !          3157: 
        !          3158:     _advise (ap);
        !          3159: 
        !          3160:     va_end (ap);
        !          3161: }
        !          3162: 
        !          3163: 
        !          3164: static void  _advise (ap)
        !          3165: va_list        ap;
        !          3166: {
        !          3167:     char    buffer[BUFSIZ];
        !          3168: 
        !          3169:     asprintf (buffer, ap);
        !          3170: 
        !          3171:     (void) fflush (stdout);
        !          3172: 
        !          3173:     fprintf (stderr, "%s: ", myname);
        !          3174:     (void) fputs (buffer, stderr);
        !          3175:     (void) fputc ('\n', stderr);
        !          3176: 
        !          3177:     (void) fflush (stderr);
        !          3178: }
        !          3179: #else
        !          3180: /* VARARGS */
        !          3181: 
        !          3182: void   advise (what, fmt)
        !          3183: char   *what,
        !          3184:        *fmt;
        !          3185: {
        !          3186:     advise (what, fmt);
        !          3187: }
        !          3188: #endif

unix.superglobalmegacorp.com

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