home *** CD-ROM | disk | FTP | other *** search
Text File | 1993-04-25 | 78.4 KB | 3,242 lines |
- Newsgroups: comp.sources.unix
- From: voodoo@hitl.washington.edu (Geoffery Coco)
- Subject: v26i194: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part11/16
- Sender: unix-sources-moderator@vix.com
- Approved: paul@vix.com
-
- Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
- Posting-Number: Volume 26, Issue 194
- Archive-Name: veos-2.0/part11
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 11 (of 16)."
- # Contents: kernel_private/src/shell/xv_native.c
- # kernel_private/src/talk/talk.c src/kernel_current/talk/talk.c
- # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:43 1993
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'kernel_private/src/shell/xv_native.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'kernel_private/src/shell/xv_native.c'\"
- else
- echo shar: Extracting \"'kernel_private/src/shell/xv_native.c'\" \(24300 characters\)
- sed "s/^X//" >'kernel_private/src/shell/xv_native.c' <<'END_OF_FILE'
- X/****************************************************************************************
- X * *
- X * file: xv_native.c *
- X * *
- X * the xlisp wrappers for the VEOS native prims. *
- X * *
- X * creation: December, 1991 *
- X * *
- X * *
- X * by Geoffrey P. Coco at the HITLab, Seattle. *
- X * *
- X ****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Copyright (C) 1992 Geoffrey P. Coco, Human Interface Technology Lab, Seattle *
- X ****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X Preliminaries
- X ****************************************************************************************/
- X
- X#include <math.h>
- X#include "xlisp.h"
- X
- X/* VEOS definitions: */
- X#include "kernel.h"
- X
- X#define DEFINE_NATIVE_GLOBS
- X#include "xv_native.h"
- X#undef DEFINE_NATIVE_GLOBS
- X
- X/****************************************************************************************/
- X
- XTVeosErr Native_MessageToLSpace();
- Xvoid Native_ShowMatchArgs();
- Xvoid Native_ShowSite();
- XTVeosErr Native_XCopySiteMatches();
- XTVeosErr Native_XRemoveSiteMatches();
- XTVeosErr Native_XInsertEltAtSite();
- Xvoid Native_NextMsg();
- XTVeosErr Native_DoThrow();
- X
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X Veos Primitive Wrappers
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Init()
- X{
- X LVAL pXReturn;
- X int iPort;
- X TVeosErr iErr;
- X
- X xlsave1(pXReturn);
- X
- X if (!moreargs())
- X iPort = TALK_BOGUS_FD;
- X else
- X iPort = getfixnum(xlgafixnum());
- X
- X xllastarg();
- X
- X
- X /** invoke veos kernel inialization **/
- X
- X iErr = Kernel_Init(iPort, Native_MessageToLSpace);
- X if (iErr == VEOS_SUCCESS) {
- X
- X
- X /** create a lisp based inspace for messages **/
- X
- X s_InSpace = xlenter("VEOS_INSPACE");
- X setvalue(s_InSpace, NIL);
- X NATIVE_INSPACE = &getvalue(s_InSpace);
- X
- X
- X /** create keyword symbols for nancy prims **/
- X
- X k_TestTime = xlenter(":TEST-TIME"); /* use with copy only */
- X k_Freq = xlenter(":FREQ"); /* use with copy, put or get */
- X
- X
- X /** setup invariant matcher settings in global param blocks **/
- X
- X Native_InitMatcherPBs();
- X
- X
- X /** make a uid return value to signify success **/
- X
- X
- X Uid2XVect(&IDENT_ADDR, &pXReturn);
- X }
- X
- X
- X xlpop();
- X
- X
- X return(pXReturn);
- X
- X } /* Native_Init */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Close()
- X{
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X
- X xllastarg();
- X
- X Kernel_Shutdown();
- X
- X return(true);
- X
- X } /* Native_Close */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Task()
- X{
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X
- X xllastarg();
- X#endif
- X
- X /** talk will call our message handler and stuff the inspace **/
- X
- X Kernel_SystemTask();
- X
- X
- X return(true);
- X
- X } /* Native_Task */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Put()
- X{
- X TVeosErr iErr;
- X TTimeStamp tNow;
- X
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X#endif
- X
- X
- X
- X /** get mandatory data argument **/
- X
- X native_putPB.pXReplaceElt = xlgetarg();
- X
- X
- X
- X /** get pattern from xlisp args **/
- X
- X iErr = Native_GetPatternArg(&native_putPB.pPatGr, NANCY_ReplaceMatch);
- X if (iErr != VEOS_SUCCESS)
- X Native_TrapErr(iErr, nil);
- X
- X
- X /** get optional frequency argument **/
- X
- X NATIVE_FREQ_ARG(native_putPB.iFreqFlag);
- X
- X
- X /** set the data time-stamp **/
- X
- X GET_TIME(tNow);
- X native_putPB.pStampTime = &tNow;
- X
- X
- X /** dispatch the matcher **/
- X
- X xlsave1(native_putPB.pXResult);
- X
- X Native_XMandR(&native_putPB);
- X
- X xlpop();
- X
- X
- X
- X /** clean up **/
- X
- X Nancy_DisposeGrouple(native_putPB.pPatGr);
- X
- X
- X
- X return (native_putPB.pXResult);
- X
- X } /* Native_Put */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Get()
- X{
- X TVeosErr iErr;
- X
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X#endif
- X
- X /** get pattern from xlisp args **/
- X
- X iErr = Native_GetPatternArg(&native_getPB.pPatGr, NANCY_RemoveMatch);
- X if (iErr != VEOS_SUCCESS)
- X Native_TrapErr(iErr, nil);
- X
- X
- X /** get optional frequency argument **/
- X
- X NATIVE_FREQ_ARG(native_getPB.iFreqFlag);
- X
- X
- X /** dispatch the matcher **/
- X
- X xlsave1(native_getPB.pXResult);
- X
- X Native_XMandR(&native_getPB);
- X
- X xlpop();
- X
- X
- X /** clean up **/
- X
- X Nancy_DisposeGrouple(native_getPB.pPatGr);
- X
- X
- X
- X return (native_getPB.pXResult);
- X
- X } /* Native_Get */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Copy()
- X{
- X TVeosErr iErr;
- X TTimeStamp tTest;
- X
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X#endif
- X
- X
- X
- X /** get pattern from xlisp args **/
- X
- X iErr = Native_GetPatternArg(&native_copyPB.pPatGr, NANCY_CopyMatch);
- X if (iErr != VEOS_SUCCESS)
- X Native_TrapErr(iErr, nil);
- X
- X
- X /** look for optional time-stamp-test **/
- X
- X NATIVE_TIME_ARG(native_copyPB.pTestTime, tTest);
- X
- X
- X /** get optional frequency argument **/
- X
- X NATIVE_FREQ_ARG(native_copyPB.iFreqFlag);
- X
- X
- X /** dispatch the matcher **/
- X
- X xlsave1(native_copyPB.pXResult);
- X
- X Native_XMandR(&native_copyPB);
- X
- X xlpop();
- X
- X
- X /** clean up **/
- X
- X Nancy_DisposeGrouple(native_copyPB.pPatGr);
- X
- X
- X
- X return (native_copyPB.pXResult);
- X
- X } /* Native_Copy */
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Throw()
- X{
- X LVAL pXData, pXDests;
- X TVeosErr iErr;
- X
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X#endif
- X
- X /** get dests argument **/
- X
- X pXDests = xlgalist();
- X
- X
- X /** get data argument **/
- X
- X pXData = xlgetarg();
- X
- X#ifndef OPTIMAL
- X xllastarg();
- X#endif
- X
- X iErr = Native_DoThrow(pXDests, pXData);
- X
- X return(iErr == VEOS_SUCCESS ? true : NIL);
- X
- X } /* Native_Throw */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Catch()
- X{
- X LVAL pSave;
- X TPElt pElt;
- X
- X#ifndef OPTIMAL
- X if (!KERNEL_INIT)
- X Native_TrapErr(NATIVE_NOKERNEL, nil);
- X
- X xllastarg();
- X#endif
- X
- X Native_NextMsg(&pSave);
- X
- X return (pSave);
- X
- X } /* Native_Catch */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_MinTime()
- X{
- X TF2L fTrans;
- X
- X /* guaranteed to be earlier than any system time */
- X
- X fTrans.u.l = NANCY_MINTIME;
- X
- X return(cvflonum(fTrans.u.f));
- X
- X } /* Native_MinTime */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_NoSignals()
- X{
- X SIG_ENABLE = FALSE;
- X
- X return(true);
- X
- X } /* Native_NoSignals */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XLVAL Native_Bugs()
- X{
- X LVAL pXModule;
- X char *sName;
- X
- X pXModule = xlgastring();
- X sName = (char *) getstring(pXModule);
- X
- X if (strcmp(sName, "talk") == 0)
- X TALK_BUGS = TALK_BUGS ? FALSE : TRUE;
- X
- X else if (strcmp(sName, "nancy") == 0)
- X NANCY_BUGS = NANCY_BUGS ? FALSE : TRUE;
- X
- X else if (strcmp(sName, "shell") == 0)
- X SHELL_BUGS = SHELL_BUGS ? FALSE : TRUE;
- X
- X return(true);
- X
- X } /* Native_Bugs */
- X/****************************************************************************************/
- X
- Xextern int iEvals;
- X
- X/****************************************************************************************/
- XLVAL Native_Zoot()
- X{
- X static int iAlreadySeen = 0;
- X int iSinceLast;
- X
- X iSinceLast = iEvals - iAlreadySeen;
- X iAlreadySeen = iEvals;
- X
- X return(cvfixnum(iSinceLast));
- X
- X } /* Native_Zoot */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X The Beuractratic Linkage Between Veos and XLISP
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Shell_LoadNativePrims()
- X{
- X#define VEOS_NATIVE_LOAD
- X#include "xv_native_prims.h"
- X#undef VEOS_NATIVE_LOAD
- X
- X return(VEOS_SUCCESS);
- X }
- X/****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Shell_BailOut(sErr)
- X char *sErr;
- X{
- X
- X xlfatal(sErr);
- X
- X /** not reached **/
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Shell_BailOut */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X The Sticky Goo Just Beneath the Wrappers
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_InitMatcherPBs()
- X{
- X /** vget settings **/
- X
- X native_getPB.pSrcGr = WORK_SPACE;
- X native_getPB.iDestroyFlag = NANCY_RemoveMatch;
- X native_getPB.pXReplaceElt = nil;
- X native_getPB.pStampTime = nil;
- X native_getPB.pTestTime = nil;
- X
- X /** vcopy settings **/
- X
- X native_copyPB.pSrcGr = WORK_SPACE;
- X native_copyPB.iDestroyFlag = NANCY_CopyMatch;
- X native_copyPB.pXReplaceElt = nil;
- X native_copyPB.pStampTime = nil;
- X
- X /** vput settings **/
- X
- X native_putPB.pSrcGr = WORK_SPACE;
- X native_putPB.iDestroyFlag = NANCY_ReplaceMatch;
- X native_putPB.pTestTime = nil;
- X
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_InitMatcherPBs */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_DoThrow(pXDests, pXData)
- X LVAL pXData, pXDests;
- X{
- X TPUidNode pDests;
- X TVeosErr iErr;
- X TMsgRec msgOut;
- X
- X
- X /** convert host/port vectors to talk uids **/
- X
- X iErr = Native_XVectsToUids(pXDests, &pDests);
- X if (iErr != VEOS_SUCCESS) {
- X Native_TrapErr(iErr, pXDests);
- X }
- X
- X /** convert data element to flat network format **/
- X
- X iErr = Native_XEltToMsgRec(pXData, &msgOut);
- X if (iErr != VEOS_SUCCESS) {
- X Native_DisposeUids(pDests);
- X Native_TrapErr(iErr, pXData);
- X }
- X
- X /** pass the flat message to veos kernel **/
- X
- X iErr = Talk_SpeakToMany(pDests, &msgOut);
- X
- X
- X Native_DisposeUids(pDests);
- X
- X return(iErr);
- X
- X } /* Native_DoThrow */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- Xvoid Native_NextMsg(hMsg)
- X LVAL *hMsg;
- X{
- X *hMsg = NIL;
- X
- X if (!null(*NATIVE_INSPACE)) {
- X
- X /** get the oldest message **/
- X
- X *hMsg = car(*NATIVE_INSPACE);
- X
- X /** remove this msg from list immediately.
- X ** first cons cell in this list will thus be garbage collected.
- X ** pass back the new msg.
- X **/
- X
- X *NATIVE_INSPACE = cdr(*NATIVE_INSPACE);
- X }
- X }
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XMandR(pMandRPB)
- X TPXMandRRec pMandRPB;
- X{
- X TVeosErr iErr;
- X TMatchRec matchSpec;
- X TPReplaceRec pSite, pSave;
- X
- X
- X /** Initialize the match record.
- X ** This record get passed through the entire match process.
- X ** The matcher uses to record sites for removal and insertion.
- X ** If the matcher returns success,
- X ** we then perform any destructive operations on the gspace.
- X **/
- X
- X matchSpec.pPatGr = pMandRPB->pPatGr;
- X matchSpec.pSrcGr = pMandRPB->pSrcGr;
- X matchSpec.iDestroyFlag = pMandRPB->iDestroyFlag;
- X matchSpec.iFreqFlag = pMandRPB->iFreqFlag;
- X matchSpec.pReplaceList = nil;
- X matchSpec.pTouchList = nil;
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X Native_ShowMatchArgs(pMandRPB);
- X#endif
- X
- X /************************************/
- X
- X iErr = Nancy_MatchGrouple(&matchSpec);
- X
- X /************************************/
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X fprintf(stderr, "nancy %s: match %s.\n",
- X WHOAMI, iErr == VEOS_SUCCESS ? "succeeded" : "failed");
- X#endif
- X
- X /** Perform any destructive operations on the gspace.
- X ** These occur in on a per-site basis.
- X ** A site is:
- X ** an enclosing grouple,
- X ** a set of element intervals,
- X ** an element index at which to insert.
- X ** Sites are generated by the matcher during matching.
- X **/
- X
- X /** perform destructive element retrieval
- X **/
- X
- X switch (pMandRPB->iDestroyFlag) {
- X
- X case NANCY_CopyMatch:
- X for (pSite = matchSpec.pReplaceList;
- X pSite && iErr == VEOS_SUCCESS;
- X pSite = pSite->pNext) {
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X Native_ShowSite(pSite);
- X#endif
- X iErr = Native_XCopySiteMatches(pSite, pMandRPB->pTestTime,
- X &pMandRPB->pXResult);
- X }
- X break;
- X
- X case NANCY_RemoveMatch:
- X for (pSite = matchSpec.pReplaceList;
- X pSite && iErr == VEOS_SUCCESS;
- X pSite = pSite->pNext) {
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X Native_ShowSite(pSite);
- X#endif
- X iErr = Native_XRemoveSiteMatches(pSite, pMandRPB->pTestTime,
- X &pMandRPB->pXResult);
- X }
- X break;
- X
- X case NANCY_ReplaceMatch:
- X for (pSite = matchSpec.pReplaceList;
- X pSite && iErr == VEOS_SUCCESS;
- X pSite = pSite->pNext) {
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X Native_ShowSite(pSite);
- X#endif
- X iErr = Native_XRemoveSiteMatches(pSite, pMandRPB->pTestTime,
- X &pMandRPB->pXResult);
- X if (iErr == VEOS_SUCCESS)
- X iErr = Native_XInsertEltAtSite(pMandRPB->pXReplaceElt,
- X pMandRPB->pStampTime, pSite);
- X }
- X break;
- X
- X case NANCY_GimmeMatch:
- X iErr = NANCY_NotSupported;
- X break;
- X
- X } /* switch */
- X
- X
- X /** perform destructive element time stamping
- X **/
- X
- X if (pMandRPB->pStampTime) {
- X
- X for (pSite = matchSpec.pTouchList;
- X pSite && iErr == VEOS_SUCCESS;
- X pSite = pSite->pNext) {
- X#ifndef OPTIMAL
- X if (NANCY_BUGS)
- X Native_ShowSite(pSite);
- X#endif
- X Native_TouchSiteMatches(pSite, *pMandRPB->pStampTime);
- X
- X }
- X }
- X
- X /** free all matcher memory (stays within veos kernel) **/
- X
- X pSite = matchSpec.pReplaceList;
- X while (pSite) {
- X pSave = pSite;
- X pSite = pSite->pNext;
- X Shell_ReturnBlock(pSave, sizeof(TReplaceRec), "replace-bp");
- X }
- X
- X pSite = matchSpec.pTouchList;
- X while (pSite) {
- X pSave = pSite;
- X pSite = pSite->pNext;
- X Shell_ReturnBlock(pSave, sizeof(TReplaceRec), "replace-bp");
- X }
- X
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** check for successful insert (give caller appropriate feeback) **/
- X
- X if (pMandRPB->iDestroyFlag == NANCY_ReplaceMatch &&
- X pMandRPB->pXResult == NIL)
- X
- X pMandRPB->pXResult = true;
- X }
- X
- X#ifndef OPTIMAL
- X else {
- X if (NANCY_BUGS)
- X Nancy_TrapErr(iErr);
- X }
- X#endif
- X
- X return(iErr);
- X
- X } /* Native_MatchAndReplace */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XCopySiteMatches(pSite, pTestTime, hXResult)
- X TPReplaceRec pSite;
- X TPTimeStamp pTestTime;
- X LVAL *hXResult;
- X{
- X int iZone, iToKill, iElt, iLeft, iRight;
- X LVAL pXElt;
- X TPElt pVElt;
- X TVeosErr iErr;
- X
- X xlsave1(pXElt);
- X
- X /** convert outgoing data into supplanted language format.
- X ** lisp is the current control language
- X **/
- X
- X if (pTestTime == nil) {
- X
- X for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
- X iLeft = pSite->pWipeList[iZone].iLeft;
- X iRight = pSite->pWipeList[iZone].iRight;
- X iToKill = iRight - iLeft + 1;
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS) {
- X fprintf(stderr, "nancy %s: left: %d right: %d\n",
- X WHOAMI, iLeft, iRight);
- X }
- X#endif
- X for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
- X iElt >= iLeft;
- X iElt--, pVElt --) {
- X
- X if (Native_VEltToXElt(pVElt, &pXElt) == VEOS_SUCCESS)
- X
- X /** assume caller protected *hXResult **/
- X *hXResult = cons(pXElt, *hXResult);
- X }
- X }
- X }
- X else {
- X
- X for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
- X iLeft = pSite->pWipeList[iZone].iLeft;
- X iRight = pSite->pWipeList[iZone].iRight;
- X iToKill = iRight - iLeft + 1;
- X
- X#ifndef OPTIMAL
- X if (NANCY_BUGS) {
- X fprintf(stderr, "nancy %s: left: %d right: %d\n",
- X WHOAMI, iLeft, iRight);
- X }
- X#endif
- X
- X for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
- X iElt >= iLeft;
- X iElt--, pVElt--) {
- X
- X iErr = Native_NewVEltToXElt(pVElt, &pXElt, *pTestTime);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** assume caller protected *hXResult **/
- X *hXResult = cons(pXElt, *hXResult);
- X }
- X /*
- X else if (iErr == NATIVE_STALE)
- X iErr = VEOS_SUCCESS;
- X */
- X }
- X }
- X }
- X
- X xlpop();
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_XCopySiteMatches */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XRemoveSiteMatches(pSite, pTestTime, hXResult)
- X TPReplaceRec pSite;
- X TPTimeStamp pTestTime;
- X LVAL *hXResult;
- X{
- X int iZone, iToKill, iElt, iLeft, iRight;
- X LVAL pXElt;
- X TPElt pVElt;
- X
- X xlsave1(pXElt);
- X
- X for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
- X iLeft = pSite->pWipeList[iZone].iLeft;
- X iRight = pSite->pWipeList[iZone].iRight;
- X iToKill = iRight - iLeft + 1;
- X
- X /** convert outgoing data into supplanted language format.
- X ** that format is xlisp, and in reverse order
- X **/
- X
- X for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
- X iElt >= iLeft;
- X iElt--, pVElt--) {
- X
- X if (Native_VEltToXElt(pVElt, &pXElt) == VEOS_SUCCESS)
- X
- X /** assume caller has protected *hXResult **/
- X
- X *hXResult = cons(pXElt, *hXResult);
- X }
- X
- X Nancy_DeleteElementsInGrouple(pSite->pEnviron,
- X iLeft,
- X iToKill);
- X }
- X
- X xlpop();
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_XRemoveSiteMatches */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_XInsertEltAtSite(pXReplaceElt, pStampTime, pSite)
- X LVAL pXReplaceElt;
- X TPTimeStamp pStampTime;
- X TPReplaceRec pSite;
- X{
- X TElt localElt;
- X TVeosErr iErr = VEOS_SUCCESS;
- X
- X if (pSite->iInsertElt >= 0) {
- X
- X localElt = NIL_ELT;
- X
- X if (pStampTime)
- X iErr = Native_XEltToNewVElt(pXReplaceElt, &localElt, *pStampTime);
- X else
- X iErr = Native_XEltToVElt(pXReplaceElt, &localElt);
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X Nancy_NewElementsInGrouple(pSite->pEnviron, pSite->iInsertElt, 1,
- X GR_unspecified, 0);
- X pSite->pEnviron->pEltList[pSite->iInsertElt] = localElt;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Native_XInsertEltAtSite */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_TouchSiteMatches(pSite, time)
- X TPReplaceRec pSite;
- X TTimeStamp time;
- X{
- X int iZone, iElt, iLeft, iRight;
- X TPElt pVElt;
- X
- X for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
- X
- X iLeft = pSite->pWipeList[iZone].iLeft;
- X iRight = pSite->pWipeList[iZone].iRight;
- X
- X /** simply update time stamp of given elements **/
- X
- X for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
- X iElt >= iLeft;
- X iElt--, pVElt--)
- X
- X pVElt->tLastMod = time;
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Native_TouchSiteMatches */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Native_MessageToLSpace(pMsgRec)
- X TPMsgRec pMsgRec;
- X{
- X TVeosErr iErr;
- X LVAL pXElt, *hFinger;
- X int iLen;
- X char *pBuf;
- X
- X
- X xlsave1(pXElt);
- X
- X /** return data to grouple form **/
- X
- X pBuf = pMsgRec->sMessage;
- X iLen = 0;
- X iErr = Native_MessageToXElt(pBuf, &pXElt, &iLen);
- X
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: results of message conversion, native: %d\n",
- X WHOAMI, iErr);
- X }
- X#endif
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: element in message:\n", WHOAMI);
- X
- X errprint(pXElt);
- X }
- X#endif
- X
- X /** append message to native inspace list **/
- X
- X hFinger = NATIVE_INSPACE;
- X while (!null(*hFinger))
- X hFinger = &cdr(*hFinger);
- X
- X *hFinger = cons(pXElt, NIL);
- X }
- X
- X xlpop();
- X
- X return(iErr);
- X
- X } /* Native_MessageToLSpace */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- Xvoid Native_ShowMatchArgs(pMandRPB)
- X TPXMandRRec pMandRPB;
- X{
- X fprintf(stderr, "nancy %s: MandR arguments.\n", WHOAMI);
- X
- X fprintf(stderr, "nancy %s: source:\n", WHOAMI);
- X Nancy_GroupleToStream(pMandRPB->pSrcGr, stderr);
- X
- X fprintf(stderr, "nancy %s: pattern:\n", WHOAMI);
- X Nancy_GroupleToStream(pMandRPB->pPatGr, stderr);
- X
- X fprintf(stderr, "nancy %s: destroyFlag: %s\n", WHOAMI,
- X pMandRPB->iDestroyFlag == NANCY_RemoveMatch ? "remove" :
- X pMandRPB->iDestroyFlag == NANCY_CopyMatch ? "copy" :
- X pMandRPB->iDestroyFlag == NANCY_ReplaceMatch ? "replace" : "unknown");
- X
- X fprintf(stderr, "nancy %s: freqFlag: %s\n", WHOAMI,
- X pMandRPB->iFreqFlag == NANCY_MatchOne ? "one" : "all");
- X
- X fprintf(stderr, "nancy %s: replace elt:\n", WHOAMI);
- X errprint(pMandRPB->pXReplaceElt);
- X
- X fprintf(stderr, "nancy %s: stamp-time: ", WHOAMI);
- X if (pMandRPB->pStampTime)
- X PRINT_TIME(*pMandRPB->pStampTime, stderr);
- X else
- X fprintf(stderr, "nil");
- X fprintf(stderr, "\n");
- X
- X fprintf(stderr, "nancy %s: test-time: ", WHOAMI);
- X if (pMandRPB->pTestTime)
- X PRINT_TIME(*pMandRPB->pTestTime, stderr);
- X else
- X fprintf(stderr, "nil");
- X fprintf(stderr, "\n");
- X
- X }
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- Xvoid Native_ShowSite(pSite)
- X TPReplaceRec pSite;
- X{
- X fprintf(stderr, "nancy %s: site grouple:\n", WHOAMI);
- X Nancy_GroupleToStream(pSite->pEnviron, stderr);
- X fprintf(stderr, "nancy %s: site zones: %d\n", WHOAMI, pSite->iZones);
- X fprintf(stderr, "nancy %s: site insert elt: %d\n", WHOAMI, pSite->iInsertElt);
- X }
- X/****************************************************************************************/
- X
- X
- X
- END_OF_FILE
- if test 24300 -ne `wc -c <'kernel_private/src/shell/xv_native.c'`; then
- echo shar: \"'kernel_private/src/shell/xv_native.c'\" unpacked with wrong size!
- fi
- # end of 'kernel_private/src/shell/xv_native.c'
- fi
- if test -f 'kernel_private/src/talk/talk.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'kernel_private/src/talk/talk.c'\"
- else
- echo shar: Extracting \"'kernel_private/src/talk/talk.c'\" \(24919 characters\)
- sed "s/^X//" >'kernel_private/src/talk/talk.c' <<'END_OF_FILE'
- X/****************************************************************************************
- X * *
- X * file: talk.c *
- X * *
- X * October 20, 1990: an entity's network interface to other entities. *
- X * *
- X * this library represents the presentation & session layers of the *
- X * ISO network systems model. *
- X * *
- X * the network and transport layers provided by socket.c *
- X * *
- X * by Geoffrey P. Coco at the HITLab, Seattle. *
- X * *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X * Copyright (C) 1992 Geoffrey P. Coco, Human Interface Technology Lab, Seattle *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X Preliminaries
- X ****************************************************************************************/
- X
- X#include "kernel.h"
- X#include "errno.h"
- X#include "sys/signal.h"
- X
- X/****************************************************************************************/
- X
- XTVeosErr Talk_DummyMsgHandler();
- X
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_HelloTalk *
- X * *
- X * talk initialization. call Talk_HelloTalk() once, and don't proceed upon failure. */
- X
- XTVeosErr Talk_HelloTalk(iPort, pMessFun)
- X int iPort;
- X TVeosErr (*pMessFun) ();
- X{
- X TVeosErr iErr;
- X
- X
- X /** allocate fast message buffers **/
- X
- X iErr = VEOS_MEM_ERR;
- X if (NEWPTR(TALK_BUFFER, char *, TALK_MAX_BUFFER)) {
- X
- X
- X /** initialize cache settings **/
- X
- X SPEAK_SET = nil;
- X
- X LISTEN_SOCKETFD = TALK_BOGUS_FD;
- X LISTEN_SET = nil;
- X
- X FD_ZERO(&OPEN_READ_SOCKETS);
- X FD_ZERO(&OPEN_WRITE_SOCKETS);
- X
- X TALK_MSG_FUNC = pMessFun ? pMessFun : Talk_DummyMsgHandler;
- X
- X bzero(SOCK_HOSTS, 26 * sizeof(TPHostNode));
- X
- X
- X /** initialize public cache settings **/
- X
- X SPEAK_DIRTY = FALSE;
- X
- X
- X
- X /** initialize listen connection **/
- X
- X iErr = Talk_OpenPort(iPort);
- X }
- X
- X return(iErr);
- X
- X } /* Talk_HelloTalk */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ByeTalk *
- X * *
- X * cleanup network and memory allocation only after finished using talk library. */
- X
- XTVeosErr Talk_ByeTalk()
- X{
- X TPSpeakNode pSpeakFinger, pTempSpeak;
- X TPListenNode pListenFinger, pTempListen;
- X
- X /** take down listen port **/
- X
- X Talk_ClosePort();
- X
- X
- X /** close all speak connections **/
- X
- X pSpeakFinger = SPEAK_SET;
- X while (pSpeakFinger) {
- X
- X pTempSpeak = pSpeakFinger->pLink;
- X
- X Talk_KillSpeakConnection(pSpeakFinger);
- X
- X pSpeakFinger = pTempSpeak;
- X }
- X
- X
- X /** close listen connections (normal mechanism is while attempting to read) **/
- X
- X pListenFinger = LISTEN_SET;
- X while (pListenFinger) {
- X
- X pTempListen = pListenFinger->pLink;
- X
- X Talk_KillListenConnection(pListenFinger);
- X
- X pListenFinger = pTempListen;
- X }
- X
- X
- X /** deallocate local library cache **/
- X
- X if (TALK_BUFFER)
- X DUMP(TALK_BUFFER);
- X
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_ByeTalk */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_SpeakToMany(pDests, pMsg)
- X TPUidNode pDests;
- X TPMsgRec pMsg;
- X{
- X TVeosErr iErr;
- X TPUidNode pFinger;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDests && pMsg) {
- X
- X iErr = VEOS_SUCCESS;
- X
- X pFinger = pDests;
- X while (pFinger && iErr == VEOS_SUCCESS) {
- X
- X iErr = Talk_PostSpeakMessage(&pFinger->addr, pMsg);
- X
- X pFinger = pFinger->pNext;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_SpeakToMany */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * private functions *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X * Talk_OpenPort *
- X * *
- X * establish an incoming message gateway for the entity client. *
- X * Talk_OpenPort() should be paired with a call to Talk_ClosePort(). */
- X
- XTVeosErr Talk_OpenPort(iPort)
- X int iPort;
- X{
- X TVeosErr iErr;
- X boolean bFound;
- X
- X
- X /** install entity connection handler **/
- X/*
- X signal(SIGIO, Talk_ConnectTrap);
- X*/
- X
- X
- X /** initiate network comminication. alert world of our existence. **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: trying to listen...\n", WHOAMI);
- X
- X
- X if (iPort != TALK_BOGUS_PORT) {
- X
- X /** use chosen port number **/
- X
- X iErr = Sock_Listen(&LISTEN_SOCKETFD,
- X iPort,
- X "tcp",
- X TALK_AGRESSIVE);
- X }
- X else {
- X /** try all sockets until we find an unused one **/
- X
- X iPort = TALK_MIN_PORT;
- X iErr = VEOS_FAILURE;
- X
- X while (iErr != VEOS_SUCCESS &&
- X iPort < TALK_MAX_PORT) {
- X
- X iErr = Sock_Listen(&LISTEN_SOCKETFD,
- X iPort,
- X "tcp",
- X TALK_PASSIVE);
- X if (iErr != VEOS_SUCCESS)
- X iPort ++;
- X }
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: cannot listen, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X }
- X
- X else {
- X /** maintain references to entity uid **/
- X
- X IDENT_ADDR.iPort = iPort;
- X Shell_UpdateUid();
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: successful listen\n", WHOAMI);
- X
- X
- X /** setup shared memory channel **/
- X
- X iErr = ShMem_Init();
- X }
- X
- X return(iErr);
- X
- X } /* Talk_OpenPort */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ClosePort *
- X * *
- X * close the incoming message gateway. the cleanup counterpart to Talk_OpenTalk(). */
- X
- XTVeosErr Talk_ClosePort()
- X{
- X TVeosErr iErr;
- X
- X
- X /** unregister ourselves from net **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: about to close main listen socket: %d, sys: %d\n",
- X WHOAMI, LISTEN_SOCKETFD, errno);
- X
- X
- X iErr = Sock_Close(&LISTEN_SOCKETFD);
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closed main listen port, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X /** takedown shared memory channel **/
- X
- X ShMem_Close();
- X
- X
- X return(iErr);
- X
- X } /* Talk_ClosePort */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_GatherListenMessages()
- X{
- X TVeosErr iErr;
- X int iSocketFD;
- X THListenNode hListenFinger;
- X TPListenNode pSaveLink;
- X
- X
- X hListenFinger = &LISTEN_SET;
- X
- X while (*hListenFinger) {
- X
- X pSaveLink = *hListenFinger;
- X iSocketFD = (*hListenFinger)->iSocketFD;
- X
- X
- X /** attempt to read messages from the connection **/
- X
- X iErr = Talk_RetrieveMessages(iSocketFD);
- X if (iErr != TALK_CONN_CLOSED)
- X
- X hListenFinger = &(*hListenFinger)->pLink;
- X
- X
- X else {
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: lost connection on socket: %d\n",
- X WHOAMI, iSocketFD);
- X
- X pSaveLink = (*hListenFinger)->pLink;
- X
- X Talk_KillListenConnection(*hListenFinger);
- X
- X *hListenFinger = pSaveLink;
- X }
- X }
- X
- X
- X /** all shared memory messages come in through one channel **/
- X
- X ShMem_GatherMessages();
- X
- X
- X return(iErr);
- X
- X } /* Talk_GatherListenMessages */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_EstNewListenConnections */
- X
- XTVeosErr Talk_EstNewListenConnections()
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X TPListenNode pNewNode;
- X
- X iErr = Talk_NewListenConnection(LISTEN_SOCKETFD, &pNewNode);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** store this record locally **/
- X
- X pNewNode->pLink = LISTEN_SET;
- X LISTEN_SET = pNewNode;
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_EstNewListenConnections */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_DispatchQedSpeakMessages()
- X{
- X TVeosErr iErr;
- X THSpeakNode hSpeakFinger;
- X TPSpeakNode pSaveLink;
- X boolean bLocalDirty;
- X
- X iErr = VEOS_SUCCESS;
- X
- X
- X /** inspect every open connection for queued outgoing messages **/
- X
- X hSpeakFinger = &SPEAK_SET;
- X SPEAK_DIRTY = FALSE;
- X
- X while (*hSpeakFinger) {
- X
- X
- X /** attempt to send queued messages for this connection in order **/
- X
- X iErr = Talk_ThrowMessages(*hSpeakFinger, &bLocalDirty);
- X if (iErr == TALK_CONN_CLOSED) {
- X
- X
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
- X WHOAMI,
- X (*hSpeakFinger)->destRec.lHost,
- X (*hSpeakFinger)->destRec.iPort,
- X (*hSpeakFinger)->iSocketFD);
- X
- X pSaveLink = (*hSpeakFinger)->pLink;
- X
- X Talk_KillSpeakConnection(*hSpeakFinger);
- X
- X *hSpeakFinger = pSaveLink;
- X }
- X
- X else {
- X if (bLocalDirty)
- X SPEAK_DIRTY = TRUE;
- X
- X
- X /** check next connection **/
- X
- X hSpeakFinger = &(*hSpeakFinger)->pLink;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_DispatchQedSpeakMessages */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_NewListenConnection */
- X
- XTVeosErr Talk_NewListenConnection(iListenSocketFD, hListenNode)
- X int iListenSocketFD;
- X THListenNode hListenNode;
- X{
- X TPListenNode pNewNode;
- X TVeosErr iErr;
- X int iSocketFD;
- X
- X
- X iErr = Sock_ReadSelect(iListenSocketFD);
- X if (iErr == VEOS_SUCCESS) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: another entity is trying to connect...\n",
- X WHOAMI);
- X
- X /** establish a full-duplex connection **/
- X
- X iErr = Sock_Accept(iListenSocketFD, &iSocketFD);
- X
- X if (iErr != VEOS_SUCCESS)
- X perror("talk: _Accept");
- X
- X else {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: another entity connected on socket: %d\n",
- X WHOAMI, iSocketFD);
- X
- X /** allocate listen connection record **/
- X
- X iErr = Shell_NewBlock(sizeof(TListenNode), &pNewNode, "listen node");
- X if (iErr != VEOS_SUCCESS) {
- X
- X Sock_Close(&iSocketFD);
- X }
- X
- X else {
- X /** setup connection record **/
- X
- X pNewNode->iSocketFD = iSocketFD;
- X pNewNode->pLink = nil;
- X
- X *hListenNode = pNewNode;
- X }
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_NewListenConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_KillListenConnection(pDeadNode)
- X TPListenNode pDeadNode;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDeadNode) { /* sane? */
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closing connection on socket: %d\n",
- X WHOAMI, pDeadNode->iSocketFD);
- X
- X /** strike this connection in all respects **/
- X
- X iErr = Sock_Close(&pDeadNode->iSocketFD);
- X
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closed listen connection, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X Shell_ReturnBlock(pDeadNode, sizeof(TListenNode), "listen node");
- X
- X iErr = VEOS_SUCCESS;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_KillListenConnection */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_PostSpeakMessage(pDest, pMsgBlock)
- X TPUid pDest;
- X TPMsgRec pMsgBlock;
- X{
- X TVeosErr iErr;
- X TPSpeakNode pDestNode, pSaveLink;
- X THSpeakNode hFinger;
- X boolean bLocalDirty;
- X
- X if (pDest) {
- X
- X
- X /** do we already have a connection to this destination? **/
- X
- X hFinger = &SPEAK_SET;
- X iErr = VEOS_FAILURE;
- X
- X while (*hFinger && iErr != VEOS_SUCCESS) {
- X
- X if (UID_COMPARE(&(*hFinger)->destRec, pDest)) {
- X
- X pDestNode = *hFinger;
- X iErr = VEOS_SUCCESS;
- X }
- X else
- X hFinger = &(*hFinger)->pLink;
- X }
- X
- X
- X /** attempt to connect to this destaination for the first time **/
- X
- X if (iErr != VEOS_SUCCESS) {
- X iErr = Talk_NewSpeakConnection(pDest,
- X &pDestNode);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** add connection record to local list **/
- X
- X pDestNode->pLink = SPEAK_SET;
- X SPEAK_SET = pDestNode;
- X hFinger = &SPEAK_SET;
- X }
- X }
- X
- X
- X /** add new message to this connection's queue **/
- X
- X if (iErr == VEOS_SUCCESS) {
- X iErr = Talk_AddSpeakJob(pDestNode, pMsgBlock);
- X if (iErr == VEOS_SUCCESS) {
- X
- X
- X /** attempt to send this message right now **/
- X
- X iErr = Talk_ThrowMessages(pDestNode, &bLocalDirty);
- X if (iErr == TALK_CONN_CLOSED) {
- X
- X
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
- X WHOAMI,
- X pDestNode->destRec.lHost,
- X pDestNode->destRec.iPort,
- X pDestNode->iSocketFD);
- X
- X
- X pSaveLink = pDestNode->pLink;
- X
- X Talk_KillSpeakConnection(pDestNode);
- X
- X *hFinger = pSaveLink;
- X }
- X
- X else if (bLocalDirty)
- X SPEAK_DIRTY = TRUE;
- X }
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_PostSpeakMessage */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_NewSpeakConnection */
- X
- XTVeosErr Talk_NewSpeakConnection(pDest, hSpeakNode)
- X TPUid pDest;
- X THSpeakNode hSpeakNode;
- X{
- X TPSpeakNode pNewNode;
- X int iSocketFD;
- X TPSharedRec pChannel;
- X TVeosErr iErr;
- X boolean bSharedMem;
- X
- X *hSpeakNode = nil;
- X
- X
- X /** try to connect to destination shell **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: trying to connect to entity: (%d %d)\n",
- X WHOAMI, pDest->lHost, pDest->iPort);
- X
- X
- X /** special case communications - shared memory **/
- X
- X bSharedMem = ShMem_CanShareMem(pDest);
- X
- X if (bSharedMem) {
- X iErr = ShMem_FindChannel(pDest->iPort, &pChannel);
- X }
- X else {
- X iErr = Sock_Connect(&iSocketFD,
- X pDest,
- X TALK_DEFAULT_PROTOCOL);
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: cannot connect, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X iErr = VEOS_FAILURE;
- X }
- X
- X else {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: connected to entity: (%d %d) on socket: %d\n",
- X WHOAMI, pDest->lHost, pDest->iPort, iSocketFD);
- X
- X
- X /** allocate a new connection record **/
- X
- X iErr = Shell_NewBlock(sizeof(TSpeakNode), &pNewNode, "speak node");
- X if (iErr != VEOS_SUCCESS) {
- X
- X if (!bSharedMem)
- X Sock_Close(&iSocketFD);
- X }
- X
- X else {
- X /** setup connection record **/
- X
- X bcopy(pDest, &pNewNode->destRec, sizeof(TUid));
- X
- X if (bSharedMem) {
- X pNewNode->iConnType = TALK_SHMEM_CONN;
- X }
- X else {
- X pNewNode->iSocketFD = iSocketFD;
- X pNewNode->iConnType = TALK_SOCK_CONN;
- X }
- X
- X pNewNode->pMessageQ = nil;
- X
- X
- X
- X /** return the address of record **/
- X
- X *hSpeakNode = pNewNode;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_NewSpeakConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_KillSpeakConnection(pDeadNode)
- X TPSpeakNode pDeadNode;
- X{
- X TVeosErr iErr;
- X TPMessageNode pMessageFinger, pTempLink;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDeadNode) { /* sane? */
- X
- X if (pDeadNode->iConnType == TALK_SOCK_CONN) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: closing connection on socket: %d\n",
- X WHOAMI, pDeadNode->iSocketFD);
- X
- X
- X /** close the speak connection **/
- X
- X iErr = Sock_Close(&pDeadNode->iSocketFD);
- X }
- X
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: closed speak connection, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X /** deallocate queued messages nodes **/
- X
- X pMessageFinger = pDeadNode->pMessageQ;
- X while (pMessageFinger) {
- X
- X DUMP(pMessageFinger->sMessage);
- X
- X pTempLink = pMessageFinger->pLink;
- X Shell_ReturnBlock(pMessageFinger, sizeof(TMessageNode), "message node");
- X
- X pMessageFinger = pTempLink;
- X }
- X
- X
- X /** free allocated node **/
- X
- X Shell_ReturnBlock(pDeadNode, sizeof(TSpeakNode), "speak node");
- X
- X
- X iErr = VEOS_SUCCESS;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_killSpeakConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_RetrieveMessages */
- X
- XTVeosErr Talk_RetrieveMessages(iSocketFD)
- X int iSocketFD;
- X{
- X TVeosErr iErr;
- X int iBufferSize, iMsgLen, iBytesRead;
- X TMsgRec pbMsg;
- X char *pFinger;
- X
- X /** grab each waiting message in buffer **/
- X
- X do {
- X
- X /** read size of next message from FD **/
- X
- X iBufferSize = sizeof(int);
- X
- X iErr = Sock_Receive(iSocketFD, &iMsgLen, &iBufferSize);
- X if (iErr == VEOS_SUCCESS) {
- X
- X iMsgLen = ntohl(iMsgLen);
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: incoming message size: %d\n",
- X WHOAMI, iMsgLen);
- X#endif
- X /** read actual grouple message **/
- X
- X iBytesRead = 0, pFinger = TALK_BUFFER;
- X while (iErr == VEOS_SUCCESS) {
- X
- X iBufferSize = iMsgLen - iBytesRead;
- X iErr = Sock_Receive(iSocketFD, pFinger, &iBufferSize);
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: receive returned %d bytes, talk: %d, sys: %d\n",
- X WHOAMI, iBufferSize, iErr, errno);
- X }
- X#endif
- X if (iErr == VEOS_SUCCESS) {
- X
- X iBytesRead += iBufferSize;
- X pFinger += iBufferSize;
- X
- X if (iBytesRead == iMsgLen) {
- X pbMsg.iLen = iBytesRead;
- X pbMsg.sMessage = TALK_BUFFER;
- X
- X (*TALK_MSG_FUNC) (&pbMsg);
- X break;
- X }
- X }
- X
- X /** spin and wait for remaining data.
- X ** there is a minimal possibility of deadlock
- X ** introduced here.
- X ** situations that may cause spinning to deadlock:
- X ** 1. sending an oversized message to yourself.
- X ** 2. sending an oversized message to a process
- X ** that is simultaneously sending an oversized
- X ** message to you.
- X ** Assumption: oversized messages are infrequent.
- X **/
- X else if (iBytesRead > 0 && iErr == TALK_LISTEN_BLOCKED) {
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: spinning on partial message..\n", WHOAMI);
- X#endif
- X iErr = VEOS_SUCCESS;
- X }
- X }
- X }
- X
- X } while (iErr == VEOS_SUCCESS);
- X
- X return(iErr);
- X
- X } /* Talk_RetrieveMessages */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ThrowMessages */
- X
- XTVeosErr Talk_ThrowMessages(pSpeakNode, pDirty)
- X TPSpeakNode pSpeakNode;
- X boolean *pDirty;
- X{
- X TVeosErr iErr = VEOS_FAILURE;
- X
- X *pDirty = FALSE;
- X
- X if (pSpeakNode->pMessageQ) { /* any messages? */
- X
- X if (pSpeakNode->iConnType == TALK_SOCK_CONN)
- X iErr = Talk_SendMsgsOverNet(pSpeakNode);
- X
- X else if (pSpeakNode->iConnType == TALK_SHMEM_CONN)
- X iErr = ShMem_WriteMessages(pSpeakNode);
- X
- X
- X /** mark this connection for pending messages **/
- X
- X if (pSpeakNode->pMessageQ)
- X *pDirty = TRUE;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_ThrowMessages */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_SendMsgsOverNet(pSpeakNode)
- X TPSpeakNode pSpeakNode;
- X{
- X int iLen, iMsgLen, iBytesWritten;
- X TPMessageNode pSaveLink;
- X char *pFinger;
- X int iSocketFD;
- X TVeosErr iErr = VEOS_SUCCESS;
- X
- X iSocketFD = pSpeakNode->iSocketFD;
- X
- X /** dispatch message sending...
- X ** oldest jobs first to enforce sequencing
- X **/
- X
- X do {
- X /** attempt to transmit oldest message **/
- X
- X pFinger = pSpeakNode->pMessageQ->sMessage;
- X iMsgLen = pSpeakNode->pMessageQ->iMsgLen;
- X iBytesWritten = 0;
- X
- X while (iErr == VEOS_SUCCESS) {
- X
- X
- X /** transmit the message **/
- X
- X iLen = iMsgLen - iBytesWritten;
- X iErr = Sock_Transmit(iSocketFD, pFinger, &iLen);
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "speak %s: transmit sent %d bytes, talk: %d, sys: %d\n",
- X WHOAMI, iLen, iErr, errno);
- X }
- X#endif
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X iBytesWritten += iLen;
- X pFinger += iLen;
- X
- X if (iBytesWritten == iMsgLen) {
- X
- X /** dequeue this message from connection record **/
- X
- X DUMP(pSpeakNode->pMessageQ->sMessage);
- X
- X pSaveLink = pSpeakNode->pMessageQ->pLink;
- X Shell_ReturnBlock(pSpeakNode->pMessageQ,
- X sizeof(TMessageNode), "message node");
- X pSpeakNode->pMessageQ = pSaveLink;
- X
- X break;
- X }
- X }
- X
- X /** spin and wait for line to free.
- X ** there is a minimal possibility of deadlock
- X ** introduced here.
- X ** situations that may cause spinning to deadlock:
- X ** 1. sending an oversized message to yourself.
- X ** 2. sending an oversized message to a process
- X ** that is simultaneously sending an oversized
- X ** message to you.
- X ** Assumption: oversized messages are infrequent.
- X **/
- X else if (iBytesWritten > 0 && iErr == TALK_SPEAK_BLOCKED) {
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: spinning on partial message..\n", WHOAMI);
- X#endif
- X iErr = VEOS_SUCCESS;
- X }
- X
- X } /* while more to write */
- X
- X
- X } while (pSpeakNode->pMessageQ);
- X
- X return(iErr);
- X
- X } /* Talk_SendMsgsOverNet */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_AddSpeakJob */
- X
- XTVeosErr Talk_AddSpeakJob(pDestNode, pMsgBlock)
- X TPSpeakNode pDestNode;
- X TPMsgRec pMsgBlock;
- X{
- X TVeosErr iErr;
- X TPMessageNode pNewJob;
- X THMessageNode hFinger;
- X
- X /** allocate new outgoing message job record **/
- X
- X iErr = Shell_NewBlock(sizeof(TMessageNode), &pNewJob, "message node");
- X if (iErr == VEOS_SUCCESS) {
- X
- X
- X /** setup job record **/
- X
- X if (NEWPTR(pNewJob->sMessage, char *, pMsgBlock->iLen + 4)) {
- X
- X /** insert length code at front of message **/
- X *(long *) pNewJob->sMessage = htonl(pMsgBlock->iLen);
- X
- X bcopy(pMsgBlock->sMessage, pNewJob->sMessage + 4, pMsgBlock->iLen);
- X pNewJob->iMsgLen = pMsgBlock->iLen + 4;
- X pNewJob->pLink = nil;
- X
- X /** append new job to destination's message queue **/
- X
- X hFinger = &pDestNode->pMessageQ;
- X while (*hFinger)
- X hFinger = &(*hFinger)->pLink;
- X
- X *hFinger = pNewJob;
- X
- X iErr = VEOS_SUCCESS;
- X }
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X
- X /** cleanup any mess **/
- X
- X if (pNewJob) {
- X if (pNewJob->sMessage)
- X DUMP(pNewJob->sMessage);
- X Shell_ReturnBlock(pNewJob, sizeof(TMessageNode), "message node");
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_AddSpeakJob */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_DummyMsgHandler(pMsgRec)
- X TPMsgRec pMsgRec;
- X{
- X char *pBuf;
- X
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: message not converted.\n", WHOAMI);
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_DummyMsgHandler */
- X/****************************************************************************************/
- X
- X
- X#ifdef banana
- Xint Talk_ConnectTrap();
- X
- X/****************************************************************************************/
- Xint Talk_ConnectTrap(iSignal, iCode, context, pAddr)
- X int iSignal, iCode;
- X struct sigcontext *context;
- X char *pAddr;
- X{
- X if (iSignal == SIGIO)
- X NEW_CONN = TRUE;
- X
- X return(0);
- X }
- X/****************************************************************************************/
- X#endif
- X
- X
- X
- X
- X
- X
- X
- X
- END_OF_FILE
- if test 24919 -ne `wc -c <'kernel_private/src/talk/talk.c'`; then
- echo shar: \"'kernel_private/src/talk/talk.c'\" unpacked with wrong size!
- fi
- # end of 'kernel_private/src/talk/talk.c'
- fi
- if test -f 'src/kernel_current/talk/talk.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/kernel_current/talk/talk.c'\"
- else
- echo shar: Extracting \"'src/kernel_current/talk/talk.c'\" \(24919 characters\)
- sed "s/^X//" >'src/kernel_current/talk/talk.c' <<'END_OF_FILE'
- X/****************************************************************************************
- X * *
- X * file: talk.c *
- X * *
- X * October 20, 1990: an entity's network interface to other entities. *
- X * *
- X * this library represents the presentation & session layers of the *
- X * ISO network systems model. *
- X * *
- X * the network and transport layers provided by socket.c *
- X * *
- X * by Geoffrey P. Coco at the HITLab, Seattle. *
- X * *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X * Copyright (C) 1992 Geoffrey P. Coco, Human Interface Technology Lab, Seattle *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X Preliminaries
- X ****************************************************************************************/
- X
- X#include "kernel.h"
- X#include "errno.h"
- X#include "sys/signal.h"
- X
- X/****************************************************************************************/
- X
- XTVeosErr Talk_DummyMsgHandler();
- X
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_HelloTalk *
- X * *
- X * talk initialization. call Talk_HelloTalk() once, and don't proceed upon failure. */
- X
- XTVeosErr Talk_HelloTalk(iPort, pMessFun)
- X int iPort;
- X TVeosErr (*pMessFun) ();
- X{
- X TVeosErr iErr;
- X
- X
- X /** allocate fast message buffers **/
- X
- X iErr = VEOS_MEM_ERR;
- X if (NEWPTR(TALK_BUFFER, char *, TALK_MAX_BUFFER)) {
- X
- X
- X /** initialize cache settings **/
- X
- X SPEAK_SET = nil;
- X
- X LISTEN_SOCKETFD = TALK_BOGUS_FD;
- X LISTEN_SET = nil;
- X
- X FD_ZERO(&OPEN_READ_SOCKETS);
- X FD_ZERO(&OPEN_WRITE_SOCKETS);
- X
- X TALK_MSG_FUNC = pMessFun ? pMessFun : Talk_DummyMsgHandler;
- X
- X bzero(SOCK_HOSTS, 26 * sizeof(TPHostNode));
- X
- X
- X /** initialize public cache settings **/
- X
- X SPEAK_DIRTY = FALSE;
- X
- X
- X
- X /** initialize listen connection **/
- X
- X iErr = Talk_OpenPort(iPort);
- X }
- X
- X return(iErr);
- X
- X } /* Talk_HelloTalk */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ByeTalk *
- X * *
- X * cleanup network and memory allocation only after finished using talk library. */
- X
- XTVeosErr Talk_ByeTalk()
- X{
- X TPSpeakNode pSpeakFinger, pTempSpeak;
- X TPListenNode pListenFinger, pTempListen;
- X
- X /** take down listen port **/
- X
- X Talk_ClosePort();
- X
- X
- X /** close all speak connections **/
- X
- X pSpeakFinger = SPEAK_SET;
- X while (pSpeakFinger) {
- X
- X pTempSpeak = pSpeakFinger->pLink;
- X
- X Talk_KillSpeakConnection(pSpeakFinger);
- X
- X pSpeakFinger = pTempSpeak;
- X }
- X
- X
- X /** close listen connections (normal mechanism is while attempting to read) **/
- X
- X pListenFinger = LISTEN_SET;
- X while (pListenFinger) {
- X
- X pTempListen = pListenFinger->pLink;
- X
- X Talk_KillListenConnection(pListenFinger);
- X
- X pListenFinger = pTempListen;
- X }
- X
- X
- X /** deallocate local library cache **/
- X
- X if (TALK_BUFFER)
- X DUMP(TALK_BUFFER);
- X
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_ByeTalk */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_SpeakToMany(pDests, pMsg)
- X TPUidNode pDests;
- X TPMsgRec pMsg;
- X{
- X TVeosErr iErr;
- X TPUidNode pFinger;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDests && pMsg) {
- X
- X iErr = VEOS_SUCCESS;
- X
- X pFinger = pDests;
- X while (pFinger && iErr == VEOS_SUCCESS) {
- X
- X iErr = Talk_PostSpeakMessage(&pFinger->addr, pMsg);
- X
- X pFinger = pFinger->pNext;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_SpeakToMany */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * private functions *
- X ****************************************************************************************/
- X
- X
- X/****************************************************************************************
- X * Talk_OpenPort *
- X * *
- X * establish an incoming message gateway for the entity client. *
- X * Talk_OpenPort() should be paired with a call to Talk_ClosePort(). */
- X
- XTVeosErr Talk_OpenPort(iPort)
- X int iPort;
- X{
- X TVeosErr iErr;
- X boolean bFound;
- X
- X
- X /** install entity connection handler **/
- X/*
- X signal(SIGIO, Talk_ConnectTrap);
- X*/
- X
- X
- X /** initiate network comminication. alert world of our existence. **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: trying to listen...\n", WHOAMI);
- X
- X
- X if (iPort != TALK_BOGUS_PORT) {
- X
- X /** use chosen port number **/
- X
- X iErr = Sock_Listen(&LISTEN_SOCKETFD,
- X iPort,
- X "tcp",
- X TALK_AGRESSIVE);
- X }
- X else {
- X /** try all sockets until we find an unused one **/
- X
- X iPort = TALK_MIN_PORT;
- X iErr = VEOS_FAILURE;
- X
- X while (iErr != VEOS_SUCCESS &&
- X iPort < TALK_MAX_PORT) {
- X
- X iErr = Sock_Listen(&LISTEN_SOCKETFD,
- X iPort,
- X "tcp",
- X TALK_PASSIVE);
- X if (iErr != VEOS_SUCCESS)
- X iPort ++;
- X }
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: cannot listen, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X }
- X
- X else {
- X /** maintain references to entity uid **/
- X
- X IDENT_ADDR.iPort = iPort;
- X Shell_UpdateUid();
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: successful listen\n", WHOAMI);
- X
- X
- X /** setup shared memory channel **/
- X
- X iErr = ShMem_Init();
- X }
- X
- X return(iErr);
- X
- X } /* Talk_OpenPort */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ClosePort *
- X * *
- X * close the incoming message gateway. the cleanup counterpart to Talk_OpenTalk(). */
- X
- XTVeosErr Talk_ClosePort()
- X{
- X TVeosErr iErr;
- X
- X
- X /** unregister ourselves from net **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: about to close main listen socket: %d, sys: %d\n",
- X WHOAMI, LISTEN_SOCKETFD, errno);
- X
- X
- X iErr = Sock_Close(&LISTEN_SOCKETFD);
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closed main listen port, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X /** takedown shared memory channel **/
- X
- X ShMem_Close();
- X
- X
- X return(iErr);
- X
- X } /* Talk_ClosePort */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_GatherListenMessages()
- X{
- X TVeosErr iErr;
- X int iSocketFD;
- X THListenNode hListenFinger;
- X TPListenNode pSaveLink;
- X
- X
- X hListenFinger = &LISTEN_SET;
- X
- X while (*hListenFinger) {
- X
- X pSaveLink = *hListenFinger;
- X iSocketFD = (*hListenFinger)->iSocketFD;
- X
- X
- X /** attempt to read messages from the connection **/
- X
- X iErr = Talk_RetrieveMessages(iSocketFD);
- X if (iErr != TALK_CONN_CLOSED)
- X
- X hListenFinger = &(*hListenFinger)->pLink;
- X
- X
- X else {
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: lost connection on socket: %d\n",
- X WHOAMI, iSocketFD);
- X
- X pSaveLink = (*hListenFinger)->pLink;
- X
- X Talk_KillListenConnection(*hListenFinger);
- X
- X *hListenFinger = pSaveLink;
- X }
- X }
- X
- X
- X /** all shared memory messages come in through one channel **/
- X
- X ShMem_GatherMessages();
- X
- X
- X return(iErr);
- X
- X } /* Talk_GatherListenMessages */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_EstNewListenConnections */
- X
- XTVeosErr Talk_EstNewListenConnections()
- X{
- X TVeosErr iErr = VEOS_SUCCESS;
- X TPListenNode pNewNode;
- X
- X iErr = Talk_NewListenConnection(LISTEN_SOCKETFD, &pNewNode);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** store this record locally **/
- X
- X pNewNode->pLink = LISTEN_SET;
- X LISTEN_SET = pNewNode;
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_EstNewListenConnections */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_DispatchQedSpeakMessages()
- X{
- X TVeosErr iErr;
- X THSpeakNode hSpeakFinger;
- X TPSpeakNode pSaveLink;
- X boolean bLocalDirty;
- X
- X iErr = VEOS_SUCCESS;
- X
- X
- X /** inspect every open connection for queued outgoing messages **/
- X
- X hSpeakFinger = &SPEAK_SET;
- X SPEAK_DIRTY = FALSE;
- X
- X while (*hSpeakFinger) {
- X
- X
- X /** attempt to send queued messages for this connection in order **/
- X
- X iErr = Talk_ThrowMessages(*hSpeakFinger, &bLocalDirty);
- X if (iErr == TALK_CONN_CLOSED) {
- X
- X
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
- X WHOAMI,
- X (*hSpeakFinger)->destRec.lHost,
- X (*hSpeakFinger)->destRec.iPort,
- X (*hSpeakFinger)->iSocketFD);
- X
- X pSaveLink = (*hSpeakFinger)->pLink;
- X
- X Talk_KillSpeakConnection(*hSpeakFinger);
- X
- X *hSpeakFinger = pSaveLink;
- X }
- X
- X else {
- X if (bLocalDirty)
- X SPEAK_DIRTY = TRUE;
- X
- X
- X /** check next connection **/
- X
- X hSpeakFinger = &(*hSpeakFinger)->pLink;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_DispatchQedSpeakMessages */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_NewListenConnection */
- X
- XTVeosErr Talk_NewListenConnection(iListenSocketFD, hListenNode)
- X int iListenSocketFD;
- X THListenNode hListenNode;
- X{
- X TPListenNode pNewNode;
- X TVeosErr iErr;
- X int iSocketFD;
- X
- X
- X iErr = Sock_ReadSelect(iListenSocketFD);
- X if (iErr == VEOS_SUCCESS) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: another entity is trying to connect...\n",
- X WHOAMI);
- X
- X /** establish a full-duplex connection **/
- X
- X iErr = Sock_Accept(iListenSocketFD, &iSocketFD);
- X
- X if (iErr != VEOS_SUCCESS)
- X perror("talk: _Accept");
- X
- X else {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: another entity connected on socket: %d\n",
- X WHOAMI, iSocketFD);
- X
- X /** allocate listen connection record **/
- X
- X iErr = Shell_NewBlock(sizeof(TListenNode), &pNewNode, "listen node");
- X if (iErr != VEOS_SUCCESS) {
- X
- X Sock_Close(&iSocketFD);
- X }
- X
- X else {
- X /** setup connection record **/
- X
- X pNewNode->iSocketFD = iSocketFD;
- X pNewNode->pLink = nil;
- X
- X *hListenNode = pNewNode;
- X }
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_NewListenConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_KillListenConnection(pDeadNode)
- X TPListenNode pDeadNode;
- X{
- X TVeosErr iErr;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDeadNode) { /* sane? */
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closing connection on socket: %d\n",
- X WHOAMI, pDeadNode->iSocketFD);
- X
- X /** strike this connection in all respects **/
- X
- X iErr = Sock_Close(&pDeadNode->iSocketFD);
- X
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: closed listen connection, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X Shell_ReturnBlock(pDeadNode, sizeof(TListenNode), "listen node");
- X
- X iErr = VEOS_SUCCESS;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_KillListenConnection */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_PostSpeakMessage(pDest, pMsgBlock)
- X TPUid pDest;
- X TPMsgRec pMsgBlock;
- X{
- X TVeosErr iErr;
- X TPSpeakNode pDestNode, pSaveLink;
- X THSpeakNode hFinger;
- X boolean bLocalDirty;
- X
- X if (pDest) {
- X
- X
- X /** do we already have a connection to this destination? **/
- X
- X hFinger = &SPEAK_SET;
- X iErr = VEOS_FAILURE;
- X
- X while (*hFinger && iErr != VEOS_SUCCESS) {
- X
- X if (UID_COMPARE(&(*hFinger)->destRec, pDest)) {
- X
- X pDestNode = *hFinger;
- X iErr = VEOS_SUCCESS;
- X }
- X else
- X hFinger = &(*hFinger)->pLink;
- X }
- X
- X
- X /** attempt to connect to this destaination for the first time **/
- X
- X if (iErr != VEOS_SUCCESS) {
- X iErr = Talk_NewSpeakConnection(pDest,
- X &pDestNode);
- X if (iErr == VEOS_SUCCESS) {
- X
- X /** add connection record to local list **/
- X
- X pDestNode->pLink = SPEAK_SET;
- X SPEAK_SET = pDestNode;
- X hFinger = &SPEAK_SET;
- X }
- X }
- X
- X
- X /** add new message to this connection's queue **/
- X
- X if (iErr == VEOS_SUCCESS) {
- X iErr = Talk_AddSpeakJob(pDestNode, pMsgBlock);
- X if (iErr == VEOS_SUCCESS) {
- X
- X
- X /** attempt to send this message right now **/
- X
- X iErr = Talk_ThrowMessages(pDestNode, &bLocalDirty);
- X if (iErr == TALK_CONN_CLOSED) {
- X
- X
- X /** connection was lost from other end **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
- X WHOAMI,
- X pDestNode->destRec.lHost,
- X pDestNode->destRec.iPort,
- X pDestNode->iSocketFD);
- X
- X
- X pSaveLink = pDestNode->pLink;
- X
- X Talk_KillSpeakConnection(pDestNode);
- X
- X *hFinger = pSaveLink;
- X }
- X
- X else if (bLocalDirty)
- X SPEAK_DIRTY = TRUE;
- X }
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_PostSpeakMessage */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_NewSpeakConnection */
- X
- XTVeosErr Talk_NewSpeakConnection(pDest, hSpeakNode)
- X TPUid pDest;
- X THSpeakNode hSpeakNode;
- X{
- X TPSpeakNode pNewNode;
- X int iSocketFD;
- X TPSharedRec pChannel;
- X TVeosErr iErr;
- X boolean bSharedMem;
- X
- X *hSpeakNode = nil;
- X
- X
- X /** try to connect to destination shell **/
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: trying to connect to entity: (%d %d)\n",
- X WHOAMI, pDest->lHost, pDest->iPort);
- X
- X
- X /** special case communications - shared memory **/
- X
- X bSharedMem = ShMem_CanShareMem(pDest);
- X
- X if (bSharedMem) {
- X iErr = ShMem_FindChannel(pDest->iPort, &pChannel);
- X }
- X else {
- X iErr = Sock_Connect(&iSocketFD,
- X pDest,
- X TALK_DEFAULT_PROTOCOL);
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: cannot connect, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X iErr = VEOS_FAILURE;
- X }
- X
- X else {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: connected to entity: (%d %d) on socket: %d\n",
- X WHOAMI, pDest->lHost, pDest->iPort, iSocketFD);
- X
- X
- X /** allocate a new connection record **/
- X
- X iErr = Shell_NewBlock(sizeof(TSpeakNode), &pNewNode, "speak node");
- X if (iErr != VEOS_SUCCESS) {
- X
- X if (!bSharedMem)
- X Sock_Close(&iSocketFD);
- X }
- X
- X else {
- X /** setup connection record **/
- X
- X bcopy(pDest, &pNewNode->destRec, sizeof(TUid));
- X
- X if (bSharedMem) {
- X pNewNode->iConnType = TALK_SHMEM_CONN;
- X }
- X else {
- X pNewNode->iSocketFD = iSocketFD;
- X pNewNode->iConnType = TALK_SOCK_CONN;
- X }
- X
- X pNewNode->pMessageQ = nil;
- X
- X
- X
- X /** return the address of record **/
- X
- X *hSpeakNode = pNewNode;
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_NewSpeakConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_KillSpeakConnection(pDeadNode)
- X TPSpeakNode pDeadNode;
- X{
- X TVeosErr iErr;
- X TPMessageNode pMessageFinger, pTempLink;
- X
- X iErr = VEOS_FAILURE;
- X
- X if (pDeadNode) { /* sane? */
- X
- X if (pDeadNode->iConnType == TALK_SOCK_CONN) {
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: closing connection on socket: %d\n",
- X WHOAMI, pDeadNode->iSocketFD);
- X
- X
- X /** close the speak connection **/
- X
- X iErr = Sock_Close(&pDeadNode->iSocketFD);
- X }
- X
- X
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: closed speak connection, talk: %d, sys: %d\n",
- X WHOAMI, iErr, errno);
- X
- X
- X /** deallocate queued messages nodes **/
- X
- X pMessageFinger = pDeadNode->pMessageQ;
- X while (pMessageFinger) {
- X
- X DUMP(pMessageFinger->sMessage);
- X
- X pTempLink = pMessageFinger->pLink;
- X Shell_ReturnBlock(pMessageFinger, sizeof(TMessageNode), "message node");
- X
- X pMessageFinger = pTempLink;
- X }
- X
- X
- X /** free allocated node **/
- X
- X Shell_ReturnBlock(pDeadNode, sizeof(TSpeakNode), "speak node");
- X
- X
- X iErr = VEOS_SUCCESS;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_killSpeakConnection */
- X/****************************************************************************************/
- X
- X
- X
- X
- X/****************************************************************************************
- X * Talk_RetrieveMessages */
- X
- XTVeosErr Talk_RetrieveMessages(iSocketFD)
- X int iSocketFD;
- X{
- X TVeosErr iErr;
- X int iBufferSize, iMsgLen, iBytesRead;
- X TMsgRec pbMsg;
- X char *pFinger;
- X
- X /** grab each waiting message in buffer **/
- X
- X do {
- X
- X /** read size of next message from FD **/
- X
- X iBufferSize = sizeof(int);
- X
- X iErr = Sock_Receive(iSocketFD, &iMsgLen, &iBufferSize);
- X if (iErr == VEOS_SUCCESS) {
- X
- X iMsgLen = ntohl(iMsgLen);
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: incoming message size: %d\n",
- X WHOAMI, iMsgLen);
- X#endif
- X /** read actual grouple message **/
- X
- X iBytesRead = 0, pFinger = TALK_BUFFER;
- X while (iErr == VEOS_SUCCESS) {
- X
- X iBufferSize = iMsgLen - iBytesRead;
- X iErr = Sock_Receive(iSocketFD, pFinger, &iBufferSize);
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: receive returned %d bytes, talk: %d, sys: %d\n",
- X WHOAMI, iBufferSize, iErr, errno);
- X }
- X#endif
- X if (iErr == VEOS_SUCCESS) {
- X
- X iBytesRead += iBufferSize;
- X pFinger += iBufferSize;
- X
- X if (iBytesRead == iMsgLen) {
- X pbMsg.iLen = iBytesRead;
- X pbMsg.sMessage = TALK_BUFFER;
- X
- X (*TALK_MSG_FUNC) (&pbMsg);
- X break;
- X }
- X }
- X
- X /** spin and wait for remaining data.
- X ** there is a minimal possibility of deadlock
- X ** introduced here.
- X ** situations that may cause spinning to deadlock:
- X ** 1. sending an oversized message to yourself.
- X ** 2. sending an oversized message to a process
- X ** that is simultaneously sending an oversized
- X ** message to you.
- X ** Assumption: oversized messages are infrequent.
- X **/
- X else if (iBytesRead > 0 && iErr == TALK_LISTEN_BLOCKED) {
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "listen %s: spinning on partial message..\n", WHOAMI);
- X#endif
- X iErr = VEOS_SUCCESS;
- X }
- X }
- X }
- X
- X } while (iErr == VEOS_SUCCESS);
- X
- X return(iErr);
- X
- X } /* Talk_RetrieveMessages */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_ThrowMessages */
- X
- XTVeosErr Talk_ThrowMessages(pSpeakNode, pDirty)
- X TPSpeakNode pSpeakNode;
- X boolean *pDirty;
- X{
- X TVeosErr iErr = VEOS_FAILURE;
- X
- X *pDirty = FALSE;
- X
- X if (pSpeakNode->pMessageQ) { /* any messages? */
- X
- X if (pSpeakNode->iConnType == TALK_SOCK_CONN)
- X iErr = Talk_SendMsgsOverNet(pSpeakNode);
- X
- X else if (pSpeakNode->iConnType == TALK_SHMEM_CONN)
- X iErr = ShMem_WriteMessages(pSpeakNode);
- X
- X
- X /** mark this connection for pending messages **/
- X
- X if (pSpeakNode->pMessageQ)
- X *pDirty = TRUE;
- X }
- X
- X return(iErr);
- X
- X } /* Talk_ThrowMessages */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_SendMsgsOverNet(pSpeakNode)
- X TPSpeakNode pSpeakNode;
- X{
- X int iLen, iMsgLen, iBytesWritten;
- X TPMessageNode pSaveLink;
- X char *pFinger;
- X int iSocketFD;
- X TVeosErr iErr = VEOS_SUCCESS;
- X
- X iSocketFD = pSpeakNode->iSocketFD;
- X
- X /** dispatch message sending...
- X ** oldest jobs first to enforce sequencing
- X **/
- X
- X do {
- X /** attempt to transmit oldest message **/
- X
- X pFinger = pSpeakNode->pMessageQ->sMessage;
- X iMsgLen = pSpeakNode->pMessageQ->iMsgLen;
- X iBytesWritten = 0;
- X
- X while (iErr == VEOS_SUCCESS) {
- X
- X
- X /** transmit the message **/
- X
- X iLen = iMsgLen - iBytesWritten;
- X iErr = Sock_Transmit(iSocketFD, pFinger, &iLen);
- X#ifndef OPTIMAL
- X if (TALK_BUGS) {
- X fprintf(stderr, "speak %s: transmit sent %d bytes, talk: %d, sys: %d\n",
- X WHOAMI, iLen, iErr, errno);
- X }
- X#endif
- X
- X if (iErr == VEOS_SUCCESS) {
- X
- X iBytesWritten += iLen;
- X pFinger += iLen;
- X
- X if (iBytesWritten == iMsgLen) {
- X
- X /** dequeue this message from connection record **/
- X
- X DUMP(pSpeakNode->pMessageQ->sMessage);
- X
- X pSaveLink = pSpeakNode->pMessageQ->pLink;
- X Shell_ReturnBlock(pSpeakNode->pMessageQ,
- X sizeof(TMessageNode), "message node");
- X pSpeakNode->pMessageQ = pSaveLink;
- X
- X break;
- X }
- X }
- X
- X /** spin and wait for line to free.
- X ** there is a minimal possibility of deadlock
- X ** introduced here.
- X ** situations that may cause spinning to deadlock:
- X ** 1. sending an oversized message to yourself.
- X ** 2. sending an oversized message to a process
- X ** that is simultaneously sending an oversized
- X ** message to you.
- X ** Assumption: oversized messages are infrequent.
- X **/
- X else if (iBytesWritten > 0 && iErr == TALK_SPEAK_BLOCKED) {
- X#ifndef OPTIMAL
- X if (TALK_BUGS)
- X fprintf(stderr, "speak %s: spinning on partial message..\n", WHOAMI);
- X#endif
- X iErr = VEOS_SUCCESS;
- X }
- X
- X } /* while more to write */
- X
- X
- X } while (pSpeakNode->pMessageQ);
- X
- X return(iErr);
- X
- X } /* Talk_SendMsgsOverNet */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************
- X * Talk_AddSpeakJob */
- X
- XTVeosErr Talk_AddSpeakJob(pDestNode, pMsgBlock)
- X TPSpeakNode pDestNode;
- X TPMsgRec pMsgBlock;
- X{
- X TVeosErr iErr;
- X TPMessageNode pNewJob;
- X THMessageNode hFinger;
- X
- X /** allocate new outgoing message job record **/
- X
- X iErr = Shell_NewBlock(sizeof(TMessageNode), &pNewJob, "message node");
- X if (iErr == VEOS_SUCCESS) {
- X
- X
- X /** setup job record **/
- X
- X if (NEWPTR(pNewJob->sMessage, char *, pMsgBlock->iLen + 4)) {
- X
- X /** insert length code at front of message **/
- X *(long *) pNewJob->sMessage = htonl(pMsgBlock->iLen);
- X
- X bcopy(pMsgBlock->sMessage, pNewJob->sMessage + 4, pMsgBlock->iLen);
- X pNewJob->iMsgLen = pMsgBlock->iLen + 4;
- X pNewJob->pLink = nil;
- X
- X /** append new job to destination's message queue **/
- X
- X hFinger = &pDestNode->pMessageQ;
- X while (*hFinger)
- X hFinger = &(*hFinger)->pLink;
- X
- X *hFinger = pNewJob;
- X
- X iErr = VEOS_SUCCESS;
- X }
- X }
- X
- X
- X if (iErr != VEOS_SUCCESS) {
- X
- X /** cleanup any mess **/
- X
- X if (pNewJob) {
- X if (pNewJob->sMessage)
- X DUMP(pNewJob->sMessage);
- X Shell_ReturnBlock(pNewJob, sizeof(TMessageNode), "message node");
- X }
- X }
- X
- X return(iErr);
- X
- X } /* Talk_AddSpeakJob */
- X/****************************************************************************************/
- X
- X
- X
- X/****************************************************************************************/
- XTVeosErr Talk_DummyMsgHandler(pMsgRec)
- X TPMsgRec pMsgRec;
- X{
- X char *pBuf;
- X
- X if (TALK_BUGS) {
- X fprintf(stderr, "listen %s: message not converted.\n", WHOAMI);
- X }
- X
- X return(VEOS_SUCCESS);
- X
- X } /* Talk_DummyMsgHandler */
- X/****************************************************************************************/
- X
- X
- X#ifdef banana
- Xint Talk_ConnectTrap();
- X
- X/****************************************************************************************/
- Xint Talk_ConnectTrap(iSignal, iCode, context, pAddr)
- X int iSignal, iCode;
- X struct sigcontext *context;
- X char *pAddr;
- X{
- X if (iSignal == SIGIO)
- X NEW_CONN = TRUE;
- X
- X return(0);
- X }
- X/****************************************************************************************/
- X#endif
- X
- X
- X
- X
- X
- X
- X
- X
- END_OF_FILE
- if test 24919 -ne `wc -c <'src/kernel_current/talk/talk.c'`; then
- echo shar: \"'src/kernel_current/talk/talk.c'\" unpacked with wrong size!
- fi
- # end of 'src/kernel_current/talk/talk.c'
- fi
- echo shar: End of archive 11 \(of 16\).
- cp /dev/null ark11isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-