|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 62959 (0xf5ef) Types: TextFile Names: »isod.c«
└─⟦3d0c2be1b⟧ Bits:30001254 ISODE-5.0 Tape └─⟦eba4602b1⟧ »./isode-5.0.tar.Z« └─⟦d3ac74d73⟧ └─⟦this⟧ »isode-5.0/support/isod.c«
/* isod.c - "minimal" ISODE server for testing */ #ifndef lint static char *rcsid = "$Header: /f/osi/support/RCS/isod.c,v 6.0 89/03/18 23:44:41 mrose Rel $"; #endif /* * $Header: /f/osi/support/RCS/isod.c,v 6.0 89/03/18 23:44:41 mrose Rel $ * * * $Log: isod.c,v $ * Revision 6.0 89/03/18 23:44:41 mrose * Release 5.0 * */ /* * NOTICE * * Acquisition, use, and distribution of this module and related * materials are subject to the restrictions of a license agreement. * Consult the Preface in the User's Manual for the full terms of * this agreement. * */ #include <stdio.h> #include <varargs.h> #include "rosap.h" #include "rtsap.h" #include "acsap.h" #include "psap2.h" #include "ssap.h" #include "tsap.h" #include "isoservent.h" #include "tailor.h" /* \f DATA */ static int debug = 0; static int isacs = 0; static int isrts = 0; static LLog _pgm_log = { "isod.log", NULLCP, NULLCP, LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, LLOGCLS | LLOGCRT | LLOGZER, NOTOK }; LLog *pgm_log = &_pgm_log; static char *myname = "isod"; static enum mode { echo, sink, XXX } mymode = XXX; struct dispatch { char *ds_entity; enum mode ds_mode; }; void adios (), advise (); void ts_adios (), ts_advise (); int ts_dataindication (), ts_discindication (); static struct dispatch ts_dispatches[] = { "echo", echo, "sink", sink, NULLCP, XXX }; void ss_adios (), ss_advise (); int ss_dataindication (), ss_tokenindication (), ss_syncindication (), ss_actindication (), ss_reportindication (), ss_finishindication (), ss_abortindication (); static struct dispatch *ss_dispatches = ts_dispatches; void ps_adios (), ps_advise (); int ps_dataindication (), ps_tokenindication (), ps_syncindication (), ps_actindication (), ps_reportindication (), ps_finishindication (), ps_abortindication (); static struct dispatch *ps_dispatches = ts_dispatches; void acs_adios (), acs_advise (); static struct dispatch acs_dispatches[] = { "isode echo", echo, "isode sink", sink, NULLCP, XXX }; void rts_adios (), rts_advise (); int rts_indication (); static struct dispatch rts_dispatches[] = { "echo", echo, "sink", sink, "ros_echo", echo, "ros_sink", sink, NULLCP, XXX }; static struct dispatch rtse_dispatches[] = { "isode rtse echo", echo, "isode rtse sink", sink, "isode ros_echo", echo, "isode ros_sink", sink, NULLCP, XXX }; static PE apdupe = NULLPE; void ros_adios (), ros_advise (); int ros_indication (); static struct dispatch *ros_dispatches = ts_dispatches; static PE nullpe = NULLPE; extern int errno; /* \f MAIN */ /* ARGSUSED */ main (argc, argv, envp) int argc; char **argv, **envp; { register char *cp; if (myname = rindex (argv[0], '/')) myname++; if (myname == NULL || *myname == NULL) myname = argv[0]; isodetailor (myname, 0); if (debug = isatty (fileno (stderr))) ll_dbinit (pgm_log, myname); else ll_hdinit (pgm_log, myname); advise (LLOG_NOTICE, NULLCP, "starting"); if (cp = rindex (*argv, '.')) *cp++ = NULL; /* cheat! should do this after calling the init function (sigh!) */ if (argc > 1 && strcmp (argv[1], "-rtse") == 0) isacs++; if (cp == NULL || strcmp (cp, "tsap") == 0) ts_main (argc, argv); else if (strcmp (cp, "ssap") == 0) ss_main (argc, argv); else if (strcmp (cp, "psap") == 0) ps_main (argc, argv); else if (strcmp (cp, "acsap") == 0) { isacs++; ps_main (argc, argv); } else if (strcmp (cp, "rtsap") == 0) { isrts++; rts_main (argc, argv); } else if (strcmp (cp, "rosap") == 0) ros_main (argc, argv); else adios (NULLCP, "unknown provider: \"%s\"", cp); exit (0); /* NOTREACHED */ } /* \f TSAP */ static int ts_main (argc, argv) int argc; char **argv; { int async, sd; char buffer[BUFSIZ]; register struct dispatch *ds; register struct isoservent *is; struct TSAPstart tss; register struct TSAPstart *ts = &tss; struct TSAPdata txs; register struct TSAPdata *tx = &txs; struct TSAPdisconnect tds; register struct TSAPdisconnect *td = &tds; if (TInit (argc, argv, ts, td) == NOTOK) ts_adios (td, "(T)initialization fails"); advise (LLOG_NOTICE, NULLCP, "T-CONNECT.INDICATION: <%d, %s, %s, %d, %d>", ts -> ts_sd, taddr2str (&ts -> ts_calling), taddr2str (&ts -> ts_called), ts -> ts_expedited, ts -> ts_tsdusize); #ifdef DEBUG if (ts -> ts_cc > 0) advise (LLOG_DEBUG, NULLCP, "greetings: %d octets", ts -> ts_cc); #endif sd = ts -> ts_sd; if (is = getisoserventbyselector ("tsap", ts -> ts_called.ta_selector, ts -> ts_called.ta_selectlen)) for (ds = ts_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } async = 0; for (argv++; *argv; argv++) { if (strcmp (*argv, "-async") == 0) { async++; continue; } if (strcmp (*argv, "-sync") == 0) { async = 0; continue; } advise (LLOG_NOTICE, NULLCP, "unknown argument \"%s\"", *argv); } switch (mymode) { case echo: case sink: if (TConnResponse (sd, NULLTA, ts -> ts_expedited, mymode == echo ? ts -> ts_data : NULLCP, mymode == echo ? ts -> ts_cc : 0, NULLQOS, td) == NOTOK) ts_adios (td, "T-CONNECT.RESPONSE"); break; default: (void) strcpy (buffer, "entity unknown or unavailable"); if (TDiscRequest (sd, buffer, strlen (buffer) + 1, td) == NOTOK) ts_adios (td, "T-DISCONNECT.REQUEST"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } if (async) { if (TSetIndications (sd, ts_dataindication, ts_discindication, td) == NOTOK) ts_adios (td, "set ASYNC fails"); for (;;) pause (); } for (;;) { if (TReadRequest (sd, tx, NOTOK, td) == NOTOK) ts_discindication (sd, td); ts_dataindication (sd, tx); } } /* \f */ static int ts_dataindication (sd, tx) int sd; register struct TSAPdata *tx; { struct TSAPdisconnect tds; register struct TSAPdisconnect *td = &tds; if (mymode == echo) { register char *p = qb2str (&tx -> tx_qbuf); if ((tx -> tx_expedited ? TExpdRequest (sd, p, tx -> tx_cc, td) : TDataRequest (sd, p, tx -> tx_cc, td)) == NOTOK) { if (td -> td_reason == DR_NORMAL) ts_discindication (sd, td); ts_adios (td, tx -> tx_expedited ? "T-EXPEDITED-DATA.REQUEST" : "T-DATA.REQUEST"); } free (p); } TXFREE (tx); } /* \f */ /* ARGSUSED */ static int ts_discindication (sd, td) int sd; register struct TSAPdisconnect *td; { if (td -> td_reason != DR_NORMAL) ts_adios (td, "T-DISCONNECT.INDICATION"); if (td -> td_cc > 0) ts_advise (td, "T-DISCONNECT.INDICATION"); else advise (LLOG_NOTICE, NULLCP, "T-DISCONNECT.INDICATION"); exit (0); } /* \f */ static void ts_adios (td, event) register struct TSAPdisconnect *td; char *event; { ts_advise (td, event); _exit (1); } static void ts_advise (td, event) register struct TSAPdisconnect *td; char *event; { char buffer[BUFSIZ]; if (td -> td_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", TErrString (td -> td_reason), td -> td_cc, td -> td_cc, td -> td_data); else (void) sprintf (buffer, "[%s]", TErrString (td -> td_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); } /* \f SSAP */ #define RMASK \ "\020\01HALFDUPLEX\02DUPLEX\03EXPEDITED\04MINORSYNC\05MAJORSYNC\06RESYNC\ \07ACTIVITY\010NEGOTIATED\011CAPABILITY\012EXCEPTIONS\013TYPEDATA" #define TMASK "\020\01DATA\03SYNC\05ACTIVITY\07RELEASE" #define dotoken(requires,shift,bit,type) \ { \ if (requirements & requires) \ switch (ss -> ss_settings & (ST_MASK << shift)) { \ case ST_CALL_VALUE << shift: \ advise (LLOG_DEBUG, NULLCP, "%s token: choice", type); \ ss -> ss_settings &= ~(ST_MASK << shift); \ ss -> ss_settings |= ST_INIT_VALUE << shift; \ break; \ \ case ST_INIT_VALUE: \ advise (LLOG_DEBUG, NULLCP, "%s token: initiator", type); \ break; \ \ case ST_RESP_VALUE: \ advise (LLOG_DEBUG, NULLCP, "%s token: responder", type); \ owned |= bit; \ break; \ \ default: \ adios (NULLCP, "%s token: reserved", type); \ break; \ } \ } static int requirements = 0; static int owned = 0; static struct SSAPdata hxs; static struct SSAPdata *hx = &hxs; /* \f */ static int ss_main (argc, argv) int argc; char **argv; { int async, result, sd; char buffer[BUFSIZ]; register struct dispatch *ds; register struct isoservent *is; struct SSAPstart sss; register struct SSAPstart *ss = &sss; struct SSAPdata sxs; register struct SSAPdata *sx = &sxs; struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; if (SInit (argc, argv, ss, si) == NOTOK) ss_adios (sa, "(S)initialization fails"); advise (LLOG_NOTICE, NULLCP, "S-CONNECT.INDICATION: <%d, %s, %s, %s, %s, %ld, %d>", ss -> ss_sd, sprintref (&ss -> ss_connect), saddr2str (&ss -> ss_calling), saddr2str (&ss -> ss_called), sprintb (ss -> ss_requirements, RMASK), ss -> ss_isn, ss -> ss_ssdusize); #ifdef DEBUG if (ss -> ss_cc > 0) advise (LLOG_DEBUG, NULLCP, "greetings: %d octets", ss -> ss_cc); #endif sd = ss -> ss_sd; ss -> ss_requirements &= SR_HALFDUPLEX | SR_DUPLEX | SR_EXPEDITED | SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY | SR_NEGOTIATED | SR_CAPABILITY | SR_EXCEPTIONS | SR_TYPEDATA; if ((ss -> ss_requirements & SR_HALFDUPLEX) && (ss -> ss_requirements & SR_DUPLEX)) ss -> ss_requirements &= ~SR_DUPLEX; requirements = ss -> ss_requirements; advise (LLOG_DEBUG, NULLCP, "new requirements: %s", sprintb (ss -> ss_requirements, RMASK)); dotokens (); advise (LLOG_DEBUG, NULLCP, "initial tokens: %s", sprintb (owned, TMASK)); if (!(ss -> ss_requirements & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC))) ss -> ss_isn = SERIAL_NONE; if (is = getisoserventbyselector ("ssap", ss -> ss_called.sa_selector, ss -> ss_called.sa_selectlen)) for (ds = ss_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } async = 0; for (argv++; *argv; argv++) { if (strcmp (*argv, "-async") == 0) { async++; continue; } if (strcmp (*argv, "-sync") == 0) { async = 0; continue; } advise (LLOG_NOTICE, NULLCP, "unknown argument \"%s\"", *argv); } switch (mymode) { case echo: case sink: if (SConnResponse (sd, &ss -> ss_connect, NULLSA, SC_ACCEPT, ss -> ss_requirements, ss -> ss_settings, ss -> ss_isn, mymode == echo ? ss -> ss_data : NULLCP, mymode == echo ? ss -> ss_cc : 0, si) == NOTOK) ss_adios (sa, "S-CONNECT.RESPONSE (accept)"); break; default: (void) strcpy (buffer, "entity unknown or unavailable"); if (SConnResponse (sd, &ss -> ss_connect, NULLSA, SC_REJECTED, 0, 0, SERIAL_NONE, buffer, strlen (buffer + 1), si) == NOTOK) ss_adios (sa, "S-CONNECT.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } if (async) { if (SSetIndications (sd, ss_dataindication, ss_tokenindication, ss_syncindication, ss_actindication, ss_reportindication, ss_finishindication, ss_abortindication, si) == NOTOK) ss_adios (sa, "set ASYNC fails"); for (;;) pause (); } for (;;) switch (result = SReadRequest (sd, sx, NOTOK, si)) { case NOTOK: ss_abortindication (sd, sa); case OK: ss_dataindication (sd, sx); break; case DONE: switch (si -> si_type) { case SI_TOKEN: ss_tokenindication (sd, &si -> si_token); break; case SI_SYNC: ss_syncindication (sd, &si -> si_sync); break; case SI_ACTIVITY: ss_actindication (sd, &si -> si_activity); break; case SI_REPORT: ss_reportindication (sd, &si -> si_report); break; case SI_FINISH: ss_finishindication (sd, &si -> si_finish); break; default: adios (NULLCP, "unknown indication type=0x%x", si -> si_type); } break; default: adios (NULLCP, "unknown return from SReadRequest=%d", result); } } #undef dotoken /* \f */ static int ss_dataindication (sd, sx) int sd; register struct SSAPdata *sx; { char *p, buffer[BUFSIZ]; struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; #ifdef DEBUG switch (sx -> sx_type) { case SX_NORMAL: advise (LLOG_DEBUG, NULLCP, "normal data, %d bytes", sx -> sx_cc); break; case SX_EXPEDITED: advise (LLOG_DEBUG, NULLCP, "expedited data, %d bytes", sx -> sx_cc); break; case SX_TYPED: advise (LLOG_DEBUG, NULLCP, "typed data, %d bytes", sx -> sx_cc); break; case SX_CAPDIND: advise (LLOG_DEBUG, NULLCP, "capability data, %d bytes", sx -> sx_cc); break; case SX_CAPDCNF: advise (LLOG_DEBUG, NULLCP, "capability data ack, %d bytes", sx -> sx_cc); default: advise (LLOG_DEBUG, NULLCP, "unknown data indication type=0x%x, %d bytes", sx -> sx_type, sx -> sx_cc); } #endif p = NULL; switch (sx -> sx_type) { case SX_NORMAL: if (mymode == sink) break; if (requirements & SR_HALFDUPLEX) { if (hx -> sx_cc > 0) { (void) strcpy (buffer, "protocol screw-up"); if (SUAbortRequest (sd, buffer, strlen (buffer) + 1, si) == NOTOK) ss_adios (sa, "S-U-ABORT.REQUEST"); else adios (NULLCP, "protocol screw-up"); } else { *hx = *sx; /* struct copy */ hx -> sx_qbuf.qb_forw -> qb_back = hx -> sx_qbuf.qb_back -> qb_forw = &hx -> sx_qbuf; bzero ((char *) sx, sizeof *sx); sx -> sx_qbuf.qb_forw = sx -> sx_qbuf.qb_back = &sx -> sx_qbuf; if (!(owned & ST_DAT_TOKEN) && SPTokenRequest (sd, ST_DAT_TOKEN, NULLCP, 0, si) == NOTOK) ss_adios (sa, "S-TOKEN-PLEASE.REQUEST"); } } else if (SDataRequest (sd, p = qb2str (&sx -> sx_qbuf), sx -> sx_cc, si) == NOTOK) ss_adios (sa, "S-DATA.REQUEST"); break; case SX_EXPEDITED: if (mymode == sink) break; if (SExpdRequest (sd, p = qb2str (&sx -> sx_qbuf), sx -> sx_cc, si) == NOTOK) ss_adios (sa, "S-EXPEDITED-DATA.REQUEST"); break; case SX_TYPED: if (mymode == sink) break; if (STypedRequest (sd, p = qb2str (&sx -> sx_qbuf), sx -> sx_cc, si) == NOTOK) ss_adios (sa, "S-TYPED-DATA.REQUEST"); break; case SX_CAPDIND: if (SCapdResponse (sd, p = qb2str (&sx -> sx_qbuf), sx -> sx_cc, si) == NOTOK) ss_adios (sa, "S-CAPABILITY-DATA.REQUEST"); break; case SX_CAPDCNF: adios (NULLCP, "got capability data response"); default: adios (NULLCP, "unknown data indication type=0x%x", sx -> sx_type); } SXFREE (sx); if (p) free (p); } /* \f */ static int ss_tokenindication (sd, st) int sd; register struct SSAPtoken *st; { struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; #ifdef DEBUG advise (LLOG_DEBUG, NULLCP, "%s tokens: %s, %d bytes", st -> st_type == ST_PLEASE ? "please" : st -> st_type == ST_GIVE ? "give" : "control", sprintb ((int) st -> st_tokens, TMASK), st -> st_cc); #endif switch (st -> st_type) { case ST_GIVE: case ST_CONTROL: owned = st -> st_owned; break; case ST_PLEASE: break; default: adios (NULLCP, "unknown token indication type=0x%x", st -> st_type); } if ((owned & ST_DAT_TOKEN) && hx -> sx_cc > 0) { char *p; if (SDataRequest (sd, p = qb2str (&hx -> sx_qbuf), hx -> sx_cc, si) == NOTOK) ss_adios (sa, "S-DATA.REQUEST"); SXFREE (hx); free (p); bzero ((char *) hx, sizeof *hx); hx -> sx_qbuf.qb_forw = hx -> sx_qbuf.qb_back = &hx -> sx_qbuf; } switch (st -> st_type) { case ST_GIVE: break; default: if (SGTokenRequest (sd, (int) st -> st_tokens, si) == NOTOK) ss_adios (sa, "S-TOKEN-GIVE.REQUEST"); else owned &= ~st -> st_tokens; break; } STFREE (st); } /* \f */ static int ss_syncindication (sd, sn) int sd; register struct SSAPsync *sn; { struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; #ifdef DEBUG switch (sn -> sn_type) { case SN_MAJORIND: advise (LLOG_DEBUG, NULLCP, "majorsync indication %d, %d bytes", sn -> sn_ssn, sn -> sn_cc); break; case SN_MAJORCNF: advise (LLOG_DEBUG, NULLCP, "majorsync confirmation %d, %d bytes", sn -> sn_ssn, sn -> sn_cc); break; case SN_MINORIND: advise (LLOG_DEBUG, NULLCP, "minorsync indication %d%s, %d bytes", sn -> sn_ssn, sn -> sn_options == SYNC_CONFIRM ? " (wants confirmation)" : NULLCP, sn -> sn_cc); break; case SN_MINORCNF: advise (LLOG_DEBUG, NULLCP, "minorsync confirmation %d, %d bytes", sn -> sn_ssn, sn -> sn_cc); break; case SN_RESETIND: advise (LLOG_DEBUG, NULLCP, "resync indication type=%d %d, %d bytes", sn -> sn_options, sn -> sn_ssn, sn -> sn_cc); break; case SN_RESETCNF: advise (LLOG_DEBUG, NULLCP, "resync confirmation %d, %d bytes", sn -> sn_ssn, sn -> sn_cc); break; default: advise (LLOG_DEBUG, NULLCP, "unknown sync indication=0x%x, ssn=%d, %d bytes", sn -> sn_type, sn -> sn_ssn, sn -> sn_cc); break; } #endif switch (sn -> sn_type) { case SN_MAJORIND: if (SMajSyncResponse (sd, mymode == echo ? sn -> sn_data : NULL, mymode == echo ? sn -> sn_cc : 0, si) == NOTOK) ss_adios (sa, "S-MAJOR-SYNC.RESPONSE"); break; case SN_MAJORCNF: adios (NULLCP, "got majorsync confirmation"); case SN_MINORIND: if (sn -> sn_options == SYNC_CONFIRM) if (SMinSyncResponse (sd, sn -> sn_ssn, mymode == echo ? sn -> sn_data : NULL, mymode == echo ? sn -> sn_cc : 0, si) == NOTOK) ss_adios (sa, "S-MINOR-SYNC.RESPONSE"); break; case SN_MINORCNF: adios (NULLCP, "got minorsync confirmation"); case SN_RESETIND: #define dotoken(requires,shift,bit,type) \ { \ if (requirements & requires) \ switch (sn -> sn_settings & (ST_MASK << shift)) { \ case ST_CALL_VALUE << shift: \ sn -> sn_settings &= ~(ST_MASK << shift); \ sn -> sn_settings |= ST_RESP_VALUE << shift; \ case ST_RESP_VALUE << shift: \ owned |= bit; \ break; \ \ case ST_INIT_VALUE << shift: \ owned &= ~bit; \ break; \ \ default: \ adios (NULLCP, "%s token: reserved", type); \ break; \ } \ } dotokens (); #undef dotoken if (SReSyncRequest (sd, SYNC_ABANDON, SERIAL_NONE, sn -> sn_settings, mymode == echo ? sn -> sn_data : NULL, mymode == echo ? sn -> sn_cc : 0, si) == NOTOK) ss_adios (sa, "S-RESYNCHRONIZE.REQUEST"); break; case SN_RESETCNF: break; default: adios (NULLCP, "unknown sync indication type=0x%x", sn -> sn_type); } SNFREE (sn); } /* \f */ static int ss_actindication (sd, sv) int sd; register struct SSAPactivity *sv; { struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; #ifdef DEBUG switch (sv -> sv_type) { case SV_START: advise (LLOG_DEBUG, NULLCP, "activity start indication: %*.*s, %d bytes", sv -> sv_id.sd_len, sv -> sv_id.sd_len, sv -> sv_id.sd_data, sv -> sv_cc); break; case SV_RESUME: advise (LLOG_DEBUG, NULLCP, "activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d, %d bytes", sv -> sv_id.sd_len, sv -> sv_id.sd_len, sv -> sv_id.sd_data, sv -> sv_oid.sd_len, sv -> sv_oid.sd_len, sv -> sv_oid.sd_data, sprintref (&sv -> sv_connect), sv -> sv_ssn, sv -> sv_cc); break; case SV_INTRIND: advise (LLOG_DEBUG, NULLCP, "activity interrupt indication %d, %d bytes", sv -> sv_reason, sv -> sv_cc); break; case SV_INTRCNF: advise (LLOG_DEBUG, NULLCP, "activity interrupt confirmation, %d bytes", sv -> sv_cc); break; case SV_DISCIND: advise (LLOG_DEBUG, NULLCP, "activity discard indication %d, %d bytes", sv -> sv_reason, sv -> sv_cc); break; case SV_DISCCNF: advise (LLOG_DEBUG, NULLCP, "activity discard confirmation, %d bytes", sv -> sv_cc); break; case SV_ENDIND: advise (LLOG_DEBUG, NULLCP, "activity end indication %d, %d bytes", sv -> sv_ssn, sv -> sv_cc); break; case SV_ENDCNF: advise (LLOG_DEBUG, NULLCP, "activity end confirmation, %d bytes", sv -> sv_cc); break; default: advise (LLOG_DEBUG, NULLCP, "unknown activity indication=0x%x, %d bytes", sv -> sv_type, sv -> sv_cc); break; } #endif switch (sv -> sv_type) { case SV_START: case SV_RESUME: break; case SV_INTRIND: if (SActIntrResponse (sd, si) == NOTOK) ss_adios (sa, "S-ACTIVITY-INTERRUPT.RESPONSE"); owned = 0; break; case SV_INTRCNF: adios (NULLCP, "got activity interrupt confirmation"); case SV_DISCIND: if (SActDiscResponse (sd, si) == NOTOK) ss_adios (sa, "S-ACTIVITY-DISCARD.RESPONSE"); owned = 0; break; case SV_DISCCNF: adios (NULLCP, "got activity discard confirmation"); case SV_ENDIND: if (SActEndResponse (sd, mymode == echo ? sv -> sv_data : NULLCP, mymode == echo ? sv -> sv_cc : 0, si) == NOTOK) ss_adios (sa, "S-ACTIVITY-END.RESPONSE"); break; case SV_ENDCNF: adios (NULLCP, "got activity end confirmation"); default: adios (NULLCP, "unknown activity indication=0x%x", sv -> sv_type); } SVFREE (sv); } /* \f */ static int ss_reportindication (sd, sp) int sd; struct SSAPreport *sp; { struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; #ifdef DEBUG advise (LLOG_DEBUG, NULLCP, "%s report %d, %d bytes", sp -> sp_peer ? "user" : "provider", sp -> sp_reason, sp -> sp_cc); #endif if (requirements & SR_DAT_EXISTS) { if (SGTokenRequest (sd, ST_DAT_TOKEN, si) == NOTOK) ss_adios (sa, "S-TOKEN-GIVE.REQUEST"); else owned &= ~ST_DAT_TOKEN; #ifdef DEBUG advise (LLOG_DEBUG, NULLCP, "cleared"); #endif } else if (SUAbortRequest (sd, NULLCP, 0, si) == NOTOK) ss_adios (sa, "S-U-ABORT.REQUEST"); else adios (NULLCP, "aborted"); SPFREE (sp); } /* \f */ static int ss_finishindication (sd, sf) int sd; register struct SSAPfinish *sf; { struct SSAPindication sis; register struct SSAPindication *si = &sis; register struct SSAPabort *sa = &si -> si_abort; if (sf -> sf_cc > 0) advise (LLOG_NOTICE, NULLCP, "S-RELEASE.INDICATION: %d bytes", sf -> sf_cc); else advise (LLOG_NOTICE, NULLCP, "S-RELEASE.INDICATION"); if (SRelResponse (sd, SC_ACCEPT, mymode == echo ? sf -> sf_data : NULL, mymode == echo ? sf -> sf_cc : 0, si) == NOTOK) ss_adios (sa, "S-RELEASE.RESPONSE"); SFFREE (sf); exit (0); } /* ARGSUSED */ static int ss_abortindication (sd, sa) int sd; register struct SSAPabort *sa; { if (!sa -> sa_peer) ss_adios (sa, "S-P-ABORT.INDICATION"); if (sa -> sa_cc > 0) ss_advise (sa, "S-U-ABORT.INDICATION"); else advise (LLOG_NOTICE, NULLCP, "S-U-ABORT.INDICATION"); exit (1); } /* \f */ static void ss_adios (sa, event) register struct SSAPabort *sa; char *event; { ss_advise (sa, event); _exit (1); } static void ss_advise (sa, event) register struct SSAPabort *sa; char *event; { char buffer[BUFSIZ]; if (sa -> sa_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", SErrString (sa -> sa_reason), sa -> sa_cc, sa -> sa_cc, sa -> sa_data); else (void) sprintf (buffer, "[%s]", SErrString (sa -> sa_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); SAFREE (sa); } /* \f PSAP */ #define PMASK \ "\020\01MANAGEMENT\02RESTORATION" #define dotoken(requires,shift,bit,type) \ { \ if (srequirements & requires) \ switch (ps -> ps_settings & (ST_MASK << shift)) { \ case ST_CALL_VALUE << shift: \ advise (LLOG_DEBUG, NULLCP, "%s token: choice", type); \ ps -> ps_settings &= ~(ST_MASK << shift); \ ps -> ps_settings |= ST_INIT_VALUE << shift; \ break; \ \ case ST_INIT_VALUE: \ advise (LLOG_DEBUG, NULLCP, "%s token: initiator", type); \ break; \ \ case ST_RESP_VALUE: \ advise (LLOG_DEBUG, NULLCP, "%s token: responder", type); \ owned |= bit; \ break; \ \ default: \ adios (NULLCP, "%s token: reserved", type); \ break; \ } \ } static int prequirements = 0; #define srequirements requirements static struct PSAPdata ixs; static struct PSAPdata *ix = &ixs; /* \f */ static int ps_main (argc, argv) int argc; char **argv; { int async, result, sd; #ifdef DEBUG int i; #endif register struct dispatch *ds; register struct isoservent *is; struct PSAPdata pxs; register struct PSAPdata *px = &pxs; struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; struct AcSAPstart acss; register struct AcSAPstart *acs = &acss; register struct PSAPstart *ps = &acs -> acs_start; register struct PSAPctxlist *pl = &ps -> ps_ctxlist; struct AcSAPindication acis; register struct AcSAPindication *aci = &acis; register struct AcSAPabort *aca = &aci -> aci_abort; if (isacs) { if (AcInit (argc, argv, acs, aci) == NOTOK) acs_adios (aca, "(Ac)initialization fails"); advise (LLOG_NOTICE, NULLCP, "A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>", acs -> acs_sd, oid2ode (acs -> acs_context), sprintaei (&acs -> acs_callingtitle), sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo); advise (LLOG_NOTICE, NULLCP, "PSAP: <%d, %s, %s, %d, %s,", ps -> ps_sd, paddr2str (&ps -> ps_calling, NULLNA), paddr2str (&ps -> ps_called, NULLNA), pl -> pc_nctx, sprintb (ps -> ps_prequirements, PMASK)); advise (LLOG_NOTICE, NULLCP, " %s, %d, %d>", sprintb (ps -> ps_srequirements, RMASK), ps -> ps_isn, ps -> ps_ssdusize); sd = acs -> acs_sd; } else { if (PInit (argc, argv, ps, pi) == NOTOK) ps_adios (pa, "(P)initialization fails"); advise (LLOG_NOTICE, NULLCP, "P-CONNECT.INDICATION: <%d, %s, %s, %d, %s,", ps -> ps_sd, paddr2str (&ps -> ps_calling, NULLNA), paddr2str (&ps -> ps_called, NULLNA), pl -> pc_nctx, sprintb (ps -> ps_prequirements, PMASK)); advise (LLOG_NOTICE, NULLCP, " %s, %d, %d>", sprintb (ps -> ps_srequirements, RMASK), ps -> ps_isn, ps -> ps_ssdusize); sd = ps -> ps_sd; } #ifdef DEBUG if (ps -> ps_ninfo > 0) advise (LLOG_DEBUG, NULLCP, "greetings: %d elements", ps -> ps_ninfo); for (i = 0; i < pl -> pc_nctx; i++) advise (LLOG_DEBUG, NULLCP, " ctx %d: %d %s 0x%x %d", i, pl -> pc_ctx[i].pc_id, sprintoid (pl -> pc_ctx[i].pc_asn), pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result); if (ps -> ps_defctx) advise (LLOG_DEBUG, NULLCP, " default: %s %d", sprintoid (ps -> ps_defctx), ps -> ps_defctxresult); #endif ps -> ps_prequirements &= PR_MANAGEMENT | PR_RESTORATION; prequirements = ps -> ps_prequirements; advise (LLOG_DEBUG, NULLCP, "new presentation requirements: %s", sprintb (ps -> ps_prequirements, PMASK)); ps -> ps_srequirements &= SR_HALFDUPLEX | SR_DUPLEX | SR_EXPEDITED | SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC | SR_ACTIVITY | SR_NEGOTIATED | SR_CAPABILITY | SR_EXCEPTIONS | SR_TYPEDATA; if ((ps -> ps_srequirements & SR_HALFDUPLEX) && (ps -> ps_srequirements & SR_DUPLEX)) ps -> ps_srequirements &= ~SR_DUPLEX; srequirements = ps -> ps_srequirements; advise (LLOG_DEBUG, NULLCP, "new session requirements: %s", sprintb (ps -> ps_srequirements, RMASK)); dotokens (); advise (LLOG_DEBUG, NULLCP, "initial tokens: %s", sprintb (owned, TMASK)); if (!(ps -> ps_srequirements & (SR_MINORSYNC | SR_MAJORSYNC | SR_RESYNC))) ps -> ps_isn = SERIAL_NONE; if (isacs) { struct TSAPaddr *ta = &ps -> ps_called.pa_addr.sa_addr; if (is = getisoserventbyselector ("tsap", ta -> ta_selector, ta -> ta_selectlen)) for (ds = acs_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } } else if (is = getisoserventbyselector ("psap", ps -> ps_called.pa_selector, ps -> ps_called.pa_selectlen)) for (ds = ps_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } async = 0; for (argv++; *argv; argv++) { if (strcmp (*argv, "-async") == 0) { async++; continue; } if (strcmp (*argv, "-sync") == 0) { async = 0; continue; } advise (LLOG_NOTICE, NULLCP, "unknown argument \"%s\"", *argv); } if (isacs) { switch (mymode) { case echo: if (AcAssocResponse (sd, ACS_ACCEPT, ACS_USER_NULL, NULLOID, NULLAEI, NULLPA, pl, ps -> ps_defctxresult, ps -> ps_prequirements, ps -> ps_srequirements, ps -> ps_isn, ps -> ps_settings, &ps -> ps_connect, acs -> acs_info, acs -> acs_ninfo, aci) == NOTOK) acs_adios (aca, "A-ASSOCIATE.RESPONSE (accept)"); break; case sink: if (AcAssocResponse (sd, ACS_ACCEPT, ACS_USER_NULL, NULLOID, NULLAEI, NULLPA, pl, ps -> ps_defctxresult, ps -> ps_prequirements, ps -> ps_srequirements, ps -> ps_isn, ps -> ps_settings, &ps -> ps_connect, NULLPEP, 0, aci) == NOTOK) acs_adios (aca, "A-ASSOCIATE.RESPONSE (accept)"); break; default: if (AcAssocResponse (sd, ACS_PERMANENT, ACS_CONTEXT, NULLOID, NULLAEI, NULLPA, pl, ps -> ps_defctxresult, 0, 0, SERIAL_NONE, 0, &ps -> ps_connect, NULLPEP, 0, aci) == NOTOK) acs_adios (aca, "A-ASSOCIATE.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } ACSFREE (acs); { struct RoSAPindication rois; register struct RoSAPpreject *rop = &rois.roi_preject; if (RoSetService (sd, RoPService, &rois) == NOTOK) ros_adios (rop, "set RO/PS fails"); } do_ros (sd, async); return; } else { switch (mymode) { case echo: if (PConnResponse (sd, PC_ACCEPT, NULLPA, pl, ps -> ps_defctxresult, ps -> ps_prequirements, ps -> ps_srequirements, ps -> ps_isn, ps -> ps_settings, &ps -> ps_connect, ps -> ps_info, ps -> ps_ninfo, pi) == NOTOK) ps_adios (pa, "P-CONNECT.RESPONSE (accept)"); break; case sink: if (PConnResponse (sd, PC_ACCEPT, NULLPA, pl, ps -> ps_defctxresult, ps -> ps_prequirements, ps -> ps_srequirements, ps -> ps_isn, ps -> ps_settings, &ps -> ps_connect, NULLPEP, 0, pi) == NOTOK) ps_adios (pa, "P-CONNECT.RESPONSE (accept)"); break; default: if (PConnResponse (sd, PC_REJECTED, NULLPA, pl, ps -> ps_defctxresult, 0, 0, SERIAL_NONE, 0, &ps -> ps_connect, NULLPEP, 0, pi) == NOTOK) ps_adios (pa, "P-CONNECT.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } PSFREE (ps); } if (async) { if (PSetIndications (sd, ps_dataindication, ps_tokenindication, ps_syncindication, ps_actindication, ps_reportindication, ps_finishindication, ps_abortindication, pi) == NOTOK) ps_adios (pa, "set ASYNC fails"); for (;;) pause (); } for (;;) switch (result = PReadRequest (sd, px, NOTOK, pi)) { case NOTOK: ps_abortindication (sd, pa); case OK: ps_dataindication (sd, px); break; case DONE: switch (pi -> pi_type) { case PI_TOKEN: ps_tokenindication (sd, &pi -> pi_token); break; case PI_SYNC: ps_syncindication (sd, &pi -> pi_sync); break; case PI_ACTIVITY: ps_actindication (sd, &pi -> pi_activity); break; case PI_REPORT: ps_reportindication (sd, &pi -> pi_report); break; case PI_FINISH: ps_finishindication (sd, &pi -> pi_finish); break; default: adios (NULLCP, "unknown indication type=0x%x", pi -> pi_type); } break; default: adios (NULLCP, "unknown return from PReadRequest=%d", result); } } #undef dotoken /* \f */ static int ps_dataindication (sd, px) int sd; register struct PSAPdata *px; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; #ifdef DEBUG switch (px -> px_type) { case SX_NORMAL: advise (LLOG_DEBUG, NULLCP, "normal data, %d elements", px -> px_ninfo); break; case SX_EXPEDITED: advise (LLOG_DEBUG, NULLCP, "expedited data, %d elements", px -> px_ninfo); break; case SX_TYPED: advise (LLOG_DEBUG, NULLCP, "typed data, %d elements", px -> px_ninfo); break; case SX_CAPDIND: advise (LLOG_DEBUG, NULLCP, "capability data, %d elements", px -> px_ninfo); break; case SX_CAPDCNF: advise (LLOG_DEBUG, NULLCP, "capability data ack, %d elements", px -> px_ninfo); default: advise (LLOG_DEBUG, NULLCP, "unknown data indication type=0x%x, %d elements", px -> px_type, px -> px_ninfo); } #endif switch (px -> px_type) { case SX_NORMAL: if (mymode == sink) break; if (srequirements & SR_HALFDUPLEX) { if (ix -> px_ninfo) { if (PUAbortRequest (sd, NULLPEP, 0, pi) == NOTOK) ps_adios (pa, "P-U-ABORT.REQUEST"); else adios (NULLCP, "protocol screw-up"); } else { *ix = *px; /* struct copy */ bzero ((char *) px, sizeof *px); if (!(owned & ST_DAT_TOKEN) && PPTokenRequest (sd, ST_DAT_TOKEN, NULLPEP, 0, pi) == NOTOK) ps_adios (pa, "P-TOKEN-PLEASE.REQUEST"); } } else if (PDataRequest (sd, px -> px_info, px -> px_ninfo, pi) == NOTOK) ps_adios (pa, "P-DATA.REQUEST"); break; case SX_EXPEDITED: if (mymode == sink) break; if (PExpdRequest (sd, px -> px_info, px -> px_ninfo, pi) == NOTOK) ps_adios (pa, "P-EXPEDITED-DATA.REQUEST"); break; case SX_TYPED: if (mymode == sink) break; if (PTypedRequest (sd, px -> px_info, px -> px_ninfo, pi) == NOTOK) ps_adios (pa, "P-TYPED-DATA.REQUEST"); break; case SX_CAPDIND: if (PCapdResponse (sd, px -> px_info, px -> px_ninfo, pi) == NOTOK) ps_adios (pa, "P-CAPABILITY-DATA.REQUEST"); break; case SX_CAPDCNF: adios (NULLCP, "got capability data response"); default: adios (NULLCP, "unknown data indication type=0x%x", px -> px_type); } PXFREE (px); } /* \f */ static int ps_tokenindication (sd, pt) int sd; register struct PSAPtoken *pt; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; #ifdef DEBUG advise (LLOG_DEBUG, NULLCP, "%s tokens: %s, %d elements", pt -> pt_type == ST_PLEASE ? "please" : pt -> pt_type == ST_GIVE ? "give" : "control", sprintb ((int) pt -> pt_tokens, TMASK), pt -> pt_ninfo); #endif switch (pt -> pt_type) { case ST_GIVE: case ST_CONTROL: owned = pt -> pt_owned; break; case ST_PLEASE: break; default: adios (NULLCP, "unknown token indication type=0x%x", pt -> pt_type); } if ((owned & ST_DAT_TOKEN) && ix -> px_ninfo) if (PDataRequest (sd, ix -> px_info, ix -> px_ninfo, pi) == NOTOK) ps_adios (pa, "P-DATA.REQUEST"); else { PXFREE (ix); bzero ((char *) ix, sizeof *ix); } switch (pt -> pt_type) { case ST_GIVE: break; default: if (PGTokenRequest (sd, (int) pt -> pt_tokens, pi) == NOTOK) ps_adios (pa, "P-TOKEN-GIVE.REQUEST"); else owned &= ~pt -> pt_tokens; break; } PTFREE (pt); } /* \f */ static int ps_syncindication (sd, pn) int sd; register struct PSAPsync *pn; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; #ifdef DEBUG switch (pn -> pn_type) { case SN_MAJORIND: advise (LLOG_DEBUG, NULLCP, "majorsync indication %d", pn -> pn_ssn); break; case SN_MAJORCNF: advise (LLOG_DEBUG, NULLCP, "majorsync confirmation %d", pn -> pn_ssn); break; case SN_MINORIND: advise (LLOG_DEBUG, NULLCP, "minorsync indication %d%s", pn -> pn_ssn, pn -> pn_options == SYNC_CONFIRM ? " (wants confirmation)" : NULLCP); break; case SN_MINORCNF: advise (LLOG_DEBUG, NULLCP, "minorsync confirmation %d", pn -> pn_ssn); break; case SN_RESETIND: advise (LLOG_DEBUG, NULLCP, "resync indication type=%d %d", pn -> pn_options, pn -> pn_ssn); break; case SN_RESETCNF: advise (LLOG_DEBUG, NULLCP, "resync confirmation %d", pn -> pn_ssn); break; default: advise (LLOG_DEBUG, NULLCP, "unknown sync indication=0x%x, ssn=%d", pn -> pn_type, pn -> pn_ssn); break; } advise (LLOG_DEBUG, NULLCP, "%d elements", pn -> pn_ninfo); #endif switch (pn -> pn_type) { case SN_MAJORIND: if (PMajSyncResponse (sd, mymode == echo ? pn -> pn_info : NULLPEP, mymode == echo ? pn -> pn_ninfo : 0, pi) == NOTOK) ps_adios (pa, "P-MAJOR-SYNC.RESPONSE"); break; case SN_MAJORCNF: adios (NULLCP, "got majorsync confirmation"); case SN_MINORIND: if (pn -> pn_options == SYNC_CONFIRM) if (PMinSyncResponse (sd, pn -> pn_ssn, mymode == echo ? pn -> pn_info : NULLPEP, mymode == echo ? pn -> pn_ninfo : 0, pi) == NOTOK) ps_adios (pa, "P-MINOR-SYNC.RESPONSE"); break; case SN_MINORCNF: adios (NULLCP, "got minorsync confirmation"); case SN_RESETIND: #define dotoken(requires,shift,bit,type) \ { \ if (srequirements & requires) \ switch (pn -> pn_settings & (ST_MASK << shift)) { \ case ST_CALL_VALUE << shift: \ pn -> pn_settings &= ~(ST_MASK << shift); \ pn -> pn_settings |= ST_RESP_VALUE << shift; \ case ST_RESP_VALUE << shift: \ owned |= bit; \ break; \ \ case ST_INIT_VALUE << shift: \ owned &= ~bit; \ break; \ \ default: \ adios (NULLCP, "%s token: reserved", type); \ break; \ } \ } dotokens (); #undef dotoken if (PReSyncRequest (sd, SYNC_ABANDON, SERIAL_NONE, pn -> pn_settings, mymode == echo ? pn -> pn_info : NULLPEP, mymode == echo ? pn -> pn_ninfo : 0, pi) == NOTOK) ps_adios (pa, "P-RESYNCHRONIZE.REQUEST"); break; case SN_RESETCNF: break; default: adios (NULLCP, "unknown sync indication type=0x%x", pn -> pn_type); } PNFREE (pn); } /* \f */ static int ps_actindication (sd, pv) int sd; register struct PSAPactivity *pv; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; #ifdef DEBUG switch (pv -> pv_type) { case SV_START: advise (LLOG_DEBUG, NULLCP, "activity start indication: %*.*s", pv -> pv_id.sd_len, pv -> pv_id.sd_len, pv -> pv_id.sd_data); break; case SV_RESUME: advise (LLOG_DEBUG, NULLCP, "activity resume indication: id=%*.*s oid=%*.*s connect=%s ssn=%d", pv -> pv_id.sd_len, pv -> pv_id.sd_len, pv -> pv_id.sd_data, pv -> pv_oid.sd_len, pv -> pv_oid.sd_len, pv -> pv_oid.sd_data, sprintref (&pv -> pv_connect), pv -> pv_ssn); break; case SV_INTRIND: advise (LLOG_DEBUG, NULLCP, "activity interrupt indication %d", pv -> pv_reason); break; case SV_INTRCNF: advise (LLOG_DEBUG, NULLCP, "activity interrupt confirmation"); break; case SV_DISCIND: advise (LLOG_DEBUG, NULLCP, "activity discard indication %d", pv -> pv_reason); break; case SV_DISCCNF: advise (LLOG_DEBUG, NULLCP, "activity discard confirmation"); break; case SV_ENDIND: advise (LLOG_DEBUG, NULLCP, "activity end indication %d", pv -> pv_ssn); break; case SV_ENDCNF: advise (LLOG_DEBUG, NULLCP, "activity end confirmation"); break; default: advise (LLOG_DEBUG, NULLCP, "unknown activity indication=0x%x", pv -> pv_type); break; } advise (LLOG_DEBUG, NULLCP, "%d elements", pv -> pv_ninfo); #endif switch (pv -> pv_type) { case SV_START: case SV_RESUME: break; case SV_INTRIND: if (PActIntrResponse (sd, pi) == NOTOK) ps_adios (pa, "P-ACTIVITY-INTERRUPT.RESPONSE"); owned = 0; break; case SV_INTRCNF: adios (NULLCP, "got activity interrupt confirmation"); case SV_DISCIND: if (PActDiscResponse (sd, pi) == NOTOK) ps_adios (pa, "P-ACTIVITY-DISCARD.RESPONSE"); owned = 0; break; case SV_DISCCNF: adios (NULLCP, "got activity discard confirmation"); case SV_ENDIND: if (PActEndResponse (sd, mymode == echo ? pv -> pv_info : NULLPEP, mymode == echo ? pv -> pv_ninfo : 0, pi) == NOTOK) ps_adios (pa, "P-ACTIVITY-END.RESPONSE"); break; case SV_ENDCNF: adios (NULLCP, "got activity end confirmation"); default: adios (NULLCP, "unknown activity indication=0x%x", pv -> pv_type); } PVFREE (pv); } /* \f */ static int ps_reportindication (sd, pp) int sd; register struct PSAPreport *pp; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; #ifdef DEBUG advise (LLOG_NOTICE, NULLCP, "%s report %d, %d elements", pp -> pp_peer ? "user" : "provider", pp -> pp_reason, pp -> pp_ninfo); #endif if (srequirements & SR_DAT_EXISTS) { if (PGTokenRequest (sd, ST_DAT_TOKEN, pi) == NOTOK) ps_adios (pa, "P-TOKEN-GIVE.REQUEST"); else owned &= ~ST_DAT_TOKEN; #ifdef DEBUG advise (LLOG_DEBUG, NULLCP, "cleared"); #endif } else if (PUAbortRequest (sd, NULLPEP, 0, pi) == NOTOK) ps_adios (pa, "P-U-ABORT.REQUEST"); else adios (NULLCP, "aborted"); PPFREE (pp); } /* \f */ static int ps_finishindication (sd, pf) int sd; register struct PSAPfinish *pf; { struct PSAPindication pis; register struct PSAPindication *pi = &pis; register struct PSAPabort *pa = &pi -> pi_abort; struct AcSAPindication acis; register struct AcSAPabort *aca = &acis.aci_abort; register struct AcSAPfinish *acf = &acis.aci_finish; if (isacs) { if (AcFINISHser (sd, pf, &acis) == NOTOK) acs_adios (aca, "AcFINISHser"); ros_finish (sd, acf); return; } advise (LLOG_NOTICE, NULLCP, "P-RELEASE.INDICATION: %d elements", pf -> pf_ninfo); if (PRelResponse (sd, SC_ACCEPT, mymode == echo ? pf -> pf_info : NULLPEP, mymode == echo ? pf -> pf_ninfo : 0, pi) == NOTOK) ps_adios (pa, "P-RELEASE.RESPONSE"); PFFREE (pf); exit (0); } /* ARGSUSED */ static int ps_abortindication (sd, pa) int sd; register struct PSAPabort *pa; { struct AcSAPindication acis; register struct AcSAPindication *aci = &acis; register struct AcSAPabort *aca = &aci -> aci_abort; if (isacs) { if (AcABORTser (sd, pa, aci) == NOTOK) acs_adios (aca, "AcABORTser"); advise (LLOG_NOTICE, NULLCP, "A-%sABORT.INDICATION: [%s] %d elements", aca -> aca_source != ACA_USER ? "P-" : "", AcErrString (aca -> aca_reason), aca -> aca_ninfo); ACAFREE (aca); exit (1); } if (!pa -> pa_peer) ps_adios (pa, "P-P-ABORT.INDICATION"); advise (LLOG_NOTICE, NULLCP, "P-U-ABORT.INDICATION: %d elements", pa -> pa_ninfo); PAFREE (pa); exit (1); } /* \f */ static void ps_adios (pa, event) register struct PSAPabort *pa; char *event; { ps_advise (pa, event); _exit (1); } static void ps_advise (pa, event) register struct PSAPabort *pa; char *event; { char buffer[BUFSIZ]; if (pa -> pa_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", PErrString (pa -> pa_reason), pa -> pa_cc, pa -> pa_cc, pa -> pa_data); else (void) sprintf (buffer, "[%s]", PErrString (pa -> pa_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); } /* \f AcSAP */ static void acs_adios (aca, event) register struct AcSAPabort *aca; char *event; { acs_advise (aca, event); _exit (1); } static void acs_advise (aca, event) register struct AcSAPabort *aca; char *event; { char buffer[BUFSIZ]; if (aca -> aca_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", AcErrString (aca -> aca_reason), aca -> aca_cc, aca -> aca_cc, aca -> aca_data); else (void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s (source %d)", event, buffer, aca -> aca_source); } /* \f RtSAP */ static int rts_main (argc, argv) int argc; char **argv; { int async, result, ros, sd; #ifdef DEBUG int i; #endif struct dispatch *ds; struct isoservent *is; struct RtSAPstart rtss; register struct RtSAPstart *rts = &rtss; struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; register struct AcSAPstart *acs = &rts -> rts_start; register struct PSAPstart *ps = &acs -> acs_start; register struct PSAPctxlist *pl = &ps -> ps_ctxlist; if (isacs) { if (RtInit (argc, argv, rts, rti) == NOTOK) rts_adios (rta, "(Rt)initialization fails"); advise (LLOG_NOTICE, NULLCP, "RT-OPEN.INDICATION: <%d, %s, %s, 0x%x>", rts -> rts_sd, rts -> rts_mode == RTS_TWA ? "twa" : "mono", rts -> rts_turn == RTS_RESPONDER ? "responder" : "initiator", rts -> rts_data); advise (LLOG_NOTICE, NULLCP, "ACSE: <%d, %s, %s, %s, %d>", acs -> acs_sd, oid2ode (acs -> acs_context), sprintaei (&acs -> acs_callingtitle), sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo); advise (LLOG_NOTICE, NULLCP, "PSAP: <%d, %s, %s, %d, %s,", ps -> ps_sd, paddr2str (&ps -> ps_calling, NULLNA), paddr2str (&ps -> ps_called, NULLNA), pl -> pc_nctx, sprintb (ps -> ps_prequirements, PMASK)); advise (LLOG_NOTICE, NULLCP, " %s, %d, %d>", sprintb (ps -> ps_srequirements, RMASK), ps -> ps_isn, ps -> ps_ssdusize); #ifdef DEBUG { if (ps -> ps_ninfo > 0) advise (LLOG_DEBUG, NULLCP, "greetings: %d elements", ps -> ps_ninfo); for (i = 0; i < pl -> pc_nctx; i++) advise (LLOG_DEBUG, NULLCP, " ctx %d: %d %s 0x%x %d", i, pl -> pc_ctx[i].pc_id, sprintoid (pl -> pc_ctx[i].pc_asn), pl -> pc_ctx[i].pc_atn, pl -> pc_ctx[i].pc_result); if (ps -> ps_defctx) advise (LLOG_DEBUG, NULLCP, " default: %s %d", sprintoid (ps -> ps_defctx), ps -> ps_defctxresult); } #endif } else { if (RtBInit (argc, argv, rts, rti) == NOTOK) rts_adios (rta, "(RtB)initialization fails"); advise (LLOG_NOTICE, NULLCP, "RT-BEGIN.INDICATION: <%d, %s, %s, <%d, %s>, 0x%x>", rts -> rts_sd, rts -> rts_mode == RTS_TWA ? "twa" :"monologue", rts -> rts_turn == RTS_RESPONDER ? "responder" : "initiator", ntohs (rts -> rts_port), saddr2str (&rts -> rts_initiator.rta_addr), rts -> rts_data); } if (rts -> rts_data) { if ((result = prim2num (rts -> rts_data)) == NOTOK && rts -> rts_data -> pe_errno != PE_ERR_NONE) adios (NULLCP, "error decoding hello: %s", pe_error (rts -> rts_data -> pe_errno)); advise (LLOG_DEBUG, NULLCP, "received greetings of %d", result); pe_free (rts -> rts_data); if ((rts -> rts_data = int2prim (result = getpid ())) == NULLPE) adios (NULLCP, "unable to allocate hello"); } sd = rts -> rts_sd; if (isacs) { struct TSAPaddr *ta = &ps -> ps_called.pa_addr.sa_addr; if (is = getisoserventbyselector ("tsap", ta -> ta_selector, ta -> ta_selectlen)) for (ds = rtse_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } } else if (is = getisoserventbyport ("rtsap", rts -> rts_port)) for (ds = rts_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } async = 0; ros = !isacs && strncmp (is -> is_entity, "ros_", strlen ("ros_")) == 0; for (argv++; *argv; argv++) { if (strcmp (*argv, "-async") == 0) { async++; continue; } if (strcmp (*argv, "-sync") == 0) { async = 0; continue; } if (strcmp (*argv, "-rtse") == 0) continue; if (strcmp (*argv, "-rose") == 0) { ros++; continue; } advise (LLOG_NOTICE, NULLCP, "unknown argument \"%s\"", *argv); } if (isacs) { switch (mymode) { case echo: if (rts -> rts_mode == RTS_TWA) goto rtse_accept; rtse_reject: ; if (RtOpenResponse (sd, ACS_USER_NOREASON, NULLOID, NULLAEI, NULLPA, NULLPC, ps -> ps_defctxresult, NULLPE, rti) == NOTOK) rts_adios (rta, "RT-OPEN.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); case sink: if (rts -> rts_mode != RTS_TWA && rts -> rts_turn != RTS_INITIATOR) goto rtse_reject; rtse_accept: if (RtOpenResponse (sd, ACS_ACCEPT, NULLOID, NULLAEI, NULLPA, pl, ps -> ps_defctxresult, rts -> rts_data, rti) == NOTOK) rts_adios (rta, "RT-OPEN.RESPONSE (accept)"); advise (LLOG_DEBUG, NULLCP, "sent greetings of %d", result); break; default: goto rtse_reject; } } else { switch (mymode) { case echo: if (rts -> rts_mode == RTS_TWA) goto accept; reject: ; if (RtBeginResponse (sd, RTS_MODE, NULLPE, rti) == NOTOK) rts_adios (rta, "RT-BEGIN.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); case sink: if (rts -> rts_mode != RTS_TWA && rts -> rts_turn != RTS_INITIATOR) goto reject; accept: ; if (RtBeginResponse (sd, RTS_ACCEPT, rts -> rts_data, rti) == NOTOK) rts_adios (rta, "RT-BEGIN.RESPONSE (accept)"); advise (LLOG_DEBUG, NULLCP, "sent greetings of %d", result); break; default: if (RtBeginResponse (sd, RTS_VALIDATE, NULLPE, rti) == NOTOK) rts_adios (rta, "RT-BEGIN.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } } RTSFREE (rts); if (ros) { struct RoSAPindication rois; register struct RoSAPpreject *rop = &rois.roi_preject; if (RoSetService (sd, RoRtService, &rois) == NOTOK) ros_adios (rop, "set RO/RT fails"); do_ros (sd, async); return; } if (async) { if (RtSetIndications (sd, rts_indication, rti) == NOTOK) rts_adios (rta, "set ASYNC fails"); for (;;) pause (); } for (;;) switch (result = RtWaitRequest (sd, NOTOK, rti)) { case NOTOK: case OK: case DONE: rts_indication (sd, rti); break; default: adios (NULLCP, "unknown return from RtWaitRequest=%d", result); } } /* \f */ static int rts_indication (sd, rti) int sd; register struct RtSAPindication *rti; { switch (rti -> rti_type) { case RTI_TURN: rts_turn (sd, &rti -> rti_turn); break; case RTI_TRANSFER: rts_transfer (sd, &rti -> rti_transfer); break; case RTI_ABORT: rts_abort (sd, &rti -> rti_abort); break; case RTI_CLOSE: rts_close (sd, &rti -> rti_close); break; case RTI_FINISH: rts_finish (sd, &rti -> rti_finish); break; default: adios (NULLCP, "unknown indication type=%d", rti -> rti_type); } } /* \f */ static int rts_turn (sd, rtu) int sd; register struct RtSAPturn *rtu; { struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; if (rtu -> rtu_please) { if (RtGTurnRequest (sd, rti) == NOTOK) rts_adios (rta, "RT-TURN-GIVE.REQUEST"); } else if (apdupe) { if (RtTransferRequest (sd, apdupe, NOTOK, rti) == NOTOK) rts_adios (rta, "RT-TRANSFER.REQUEST"); pe_free (apdupe); apdupe = NULLPE; } } /* \f */ static int rts_transfer (sd, rtt) int sd; register struct RtSAPtransfer *rtt; { struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; static int priority = 1; if (mymode == echo) { if (apdupe) adios (NULLCP, "protocol screw-up"); if (RtPTurnRequest (sd, priority++, rti) == NOTOK) rts_adios (rta, "RT-TURN-PLEASE.REQUEST"); apdupe = rtt -> rtt_data; } else RTTFREE (rtt); } /* \f */ /* ARGSUSED */ static int rts_abort (sd, rta) int sd; register struct RtSAPabort *rta; { if (rta -> rta_peer) rts_adios (rta, "RT-U-ABORT.INDICATION"); if (RTS_FATAL (rta -> rta_reason)) rts_adios (rta, "RT-P-ABORT.INDICATION"); rts_advise (rta, "RT-P-ABORT.INDICATION"); } /* \f */ /* ARGSUSED */ static int rts_close (sd, rtc) int sd; struct RtSAPclose *rtc; { struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; advise (LLOG_NOTICE, NULLCP, "RT-END.INDICATION"); if (RtEndResponse (sd, rti) == NOTOK) rts_adios (rta, "RT-END.RESPONSE"); exit (0); } /* \f */ static int rts_finish (sd, acf) int sd; register struct AcSAPfinish *acf; { struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; advise (LLOG_NOTICE, NULLCP, "RT-CLOSE.INDICATION: %d, %d elements", acf -> acf_reason, acf -> acf_ninfo); if (RtCloseResponse (sd, ACR_NORMAL, mymode == echo ? acf -> acf_info[0] : NULLPE, rti) == NOTOK) rts_adios (rta, "RT-CLOSE.RESPONSE"); ACFFREE (acf); exit (0); } /* \f */ static void rts_adios (rta, event) register struct RtSAPabort *rta; char *event; { rts_advise (rta, event); _exit (1); } static void rts_advise (rta, event) register struct RtSAPabort *rta; char *event; { char buffer[BUFSIZ]; if (rta -> rta_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", RtErrString (rta -> rta_reason), rta -> rta_cc, rta -> rta_cc, rta -> rta_data); else (void) sprintf (buffer, "[%s]", RtErrString (rta -> rta_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); } /* \f RoSAP */ static int ros_main (argc, argv) int argc; char **argv; { int async, result, sd; struct dispatch *ds; struct isoservent *is; struct RoSAPstart ross; register struct RoSAPstart *ros = &ross; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; if (RoInit (argc, argv, ros, roi) == NOTOK) ros_adios (rop, "(Ro)initialization fails"); advise (LLOG_NOTICE, NULLCP, "RO-BEGIN.INDICATION: <%d, <%d, %s>, 0x%x>", ros -> ros_sd, ntohs (ros -> ros_port), saddr2str (&ros -> ros_initiator.roa_addr), ros -> ros_data); if (ros -> ros_data) { if ((result = prim2num (ros -> ros_data)) == NOTOK && ros -> ros_data -> pe_errno != PE_ERR_NONE) adios (NULLCP, "error decoding hello: %s", pe_error (ros -> ros_data -> pe_errno)); advise (LLOG_DEBUG, NULLCP, "received greetings of %d", result); pe_free (ros -> ros_data); if ((ros -> ros_data = int2prim (result = getpid ())) == NULLPE) adios (NULLCP, "unable to allocate hello"); } sd = ros -> ros_sd; if (is = getisoserventbyport ("rosap", ros -> ros_port)) for (ds = ros_dispatches; ds -> ds_entity; ds++) if (strcmp (ds -> ds_entity, is -> is_entity) == 0) { mymode = ds -> ds_mode; break; } async = 0; for (argv++; *argv; argv++) { if (strcmp (*argv, "-async") == 0) { async++; continue; } if (strcmp (*argv, "-sync") == 0) { async = 0; continue; } advise (LLOG_NOTICE, NULLCP, "unknown argument \"%s\"", *argv); } switch (mymode) { case echo: case sink: if (RoBeginResponse (sd, ROS_ACCEPT, ros -> ros_data, roi) == NOTOK) ros_adios (rop, "RO-BEGIN.RESPONSE (accept)"); advise (LLOG_DEBUG, NULLCP, "sent greetings of %d", result); break; default: if (RoBeginResponse (sd, ROS_VALIDATE, NULLPE, roi) == NOTOK) ros_adios (rop, "RO-BEGIN.RESPONSE (reject)"); advise (LLOG_NOTICE, NULLCP, "rejected"); exit (1); } ROSFREE (ros); do_ros (sd, async); } /* \f */ static int do_ros (sd, async) int sd, async; { int result; struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; if ((nullpe = pe_alloc (PE_CLASS_UNIV, PE_FORM_PRIM, PE_PRIM_NULL)) == NULLPE) adios (NULLCP, "unable to allocate NULL PE"); if (async) { if (RoSetIndications (sd, ros_indication, roi) == NOTOK) ros_adios (rop, "set ASYNC fails"); for (;;) pause (); } for (;;) switch (result = RoWaitRequest (sd, NOTOK, roi)) { case NOTOK: case OK: case DONE: ros_indication (sd, roi); break; default: adios (NULLCP, "unknown return from RoWaitRequest=%d", result); } } /* \f */ static int ros_indication (sd, roi) int sd; register struct RoSAPindication *roi; { switch (roi -> roi_type) { case ROI_INVOKE: ros_invoke (sd, &roi -> roi_invoke); break; case ROI_RESULT: ros_result (sd, &roi -> roi_result); break; case ROI_ERROR: ros_error (sd, &roi -> roi_error); break; case ROI_UREJECT: ros_ureject (sd, &roi -> roi_ureject); break; case ROI_PREJECT: ros_preject (sd, &roi -> roi_preject); break; case ROI_END: ros_end (sd, &roi -> roi_end); break; case ROI_FINISH: ros_finish (sd, &roi -> roi_finish); break; default: adios (NULLCP, "unknown indication type=%d", roi -> roi_type); } } /* \f */ static int ros_invoke (sd, rox) int sd; register struct RoSAPinvoke *rox; { struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; static int ff = 0; if (ff++ & 0x01) { if (RoErrorRequest (sd, rox -> rox_id, ff, mymode == echo ? rox -> rox_args : nullpe, ROS_NOPRIO, roi) == NOTOK) ros_adios (rop, "RO-ERROR.REQUEST"); } else { if (RoResultRequest (sd, rox -> rox_id, rox -> rox_op, mymode == echo ? rox -> rox_args : nullpe, ROS_NOPRIO, roi) == NOTOK) ros_adios (rop, "RO-RESULT.REQUEST"); } ROXFREE (rox); } /* \f */ static int ros_result (sd, ror) int sd; register struct RoSAPresult *ror; { struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; if (RoURejectRequest (sd, &ror -> ror_id, ROS_RRP_UNRECOG, ROS_NOPRIO, roi) == NOTOK) ros_adios (rop, "RO-REJECT-U.REQUEST"); RORFREE (ror); } /* \f */ static int ros_error (sd, roe) int sd; register struct RoSAPerror *roe; { struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; if (RoURejectRequest (sd, &roe -> roe_id, ROS_REP_UNRECOG, ROS_NOPRIO, roi) == NOTOK) ros_adios (rop, "RO-REJECT-U.REQUEST"); ROEFREE (roe); } /* \f */ /* ARGSUSED */ static int ros_ureject (sd, rou) int sd; register struct RoSAPureject *rou; { if (rou -> rou_noid) advise (LLOG_NOTICE, NULLCP, "RO-REJECT-U.INDICATION: %s", RoErrString (rou -> rou_reason)); else advise (LLOG_NOTICE, NULLCP, "RO-REJECT-U.INDICATION: %s (id=%d)", RoErrString (rou -> rou_reason), rou -> rou_id); } /* \f */ /* ARGSUSED */ static int ros_preject (sd, rop) int sd; register struct RoSAPpreject *rop; { if (ROS_FATAL (rop -> rop_reason)) ros_adios (rop, "RO-REJECT-P.INDICATION"); ros_advise (rop, "RO-REJECT-P.INDICATION"); } /* \f */ /* ARGSUSED */ static int ros_end (sd, roe) int sd; struct RoSAPend *roe; { if (isrts) { struct RtSAPindication rtis; register struct RtSAPindication *rti = &rtis; register struct RtSAPabort *rta = &rti -> rti_abort; advise (LLOG_NOTICE, NULLCP, "RT-END.INDICATION"); if (RtEndResponse (sd, rti) == NOTOK) rts_adios (rta, "RT-END.RESPONSE"); } else { struct RoSAPindication rois; register struct RoSAPindication *roi = &rois; register struct RoSAPpreject *rop = &roi -> roi_preject; advise (LLOG_NOTICE, NULLCP, "RO-END.INDICATION"); if (RoEndResponse (sd, roi) == NOTOK) ros_adios (rop, "RO-END.RESPONSE"); } exit (0); } /* \f */ static int ros_finish (sd, acf) int sd; register struct AcSAPfinish *acf; { if (isrts) { struct RtSAPindication rtis; register struct RtSAPabort *rta = &rtis.rti_abort; advise (LLOG_NOTICE, NULLCP, "RT-CLOSE.INDICATION: %d, %d elements", acf -> acf_reason, acf -> acf_ninfo); if (RtCloseResponse (sd, ACR_NORMAL, mymode == echo ? acf -> acf_info[0] : NULLPE, &rtis) == NOTOK) rts_adios (rta, "RT-CLOSE.RESPONSE"); } else { struct AcSAPindication acis; register struct AcSAPabort *aca = &acis.aci_abort; advise (LLOG_NOTICE, NULLCP, "A-RELEASE.INDICATION: %d, %d elements", acf -> acf_reason, acf -> acf_ninfo); if (AcRelResponse (sd, ACS_ACCEPT, ACR_NORMAL, mymode == echo ? acf -> acf_info : NULLPEP, mymode == echo ? acf -> acf_ninfo : 0, &acis) == NOTOK) acs_adios (aca, "A-RELEASE.RESPONSE"); } ACFFREE (acf); exit (0); } /* \f */ static void ros_adios (rop, event) register struct RoSAPpreject *rop; char *event; { ros_advise (rop, event); _exit (1); } static void ros_advise (rop, event) register struct RoSAPpreject *rop; char *event; { char buffer[BUFSIZ]; if (rop -> rop_cc > 0) (void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason), rop -> rop_cc, rop -> rop_cc, rop -> rop_data); else (void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason)); advise (LLOG_NOTICE, NULLCP, "%s: %s", event, buffer); } /* \f ERRORS */ #ifndef lint void adios (va_alist) va_dcl { va_list ap; va_start (ap); _ll_log (pgm_log, LLOG_FATAL, ap); va_end (ap); _exit (1); } #else /* VARARGS */ void adios (what, fmt) char *what, *fmt; { adios (what, fmt); } #endif #ifndef lint void advise (va_alist) va_dcl { int code; va_list ap; va_start (ap); code = va_arg (ap, int); _ll_log (pgm_log, code, ap); va_end (ap); } #else /* VARARGS */ void advise (code, what, fmt) char *what, *fmt; int code; { advise (code, what, fmt); } #endif