home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / veos-2.0 / part11 < prev    next >
Encoding:
Text File  |  1993-04-25  |  78.4 KB  |  3,242 lines

  1. Newsgroups: comp.sources.unix
  2. From: voodoo@hitl.washington.edu (Geoffery Coco)
  3. Subject: v26i194: veos-2.0 - The Virtual Environment Operating Shell, V2.0, Part11/16
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: voodoo@hitl.washington.edu (Geoffery Coco)
  8. Posting-Number: Volume 26, Issue 194
  9. Archive-Name: veos-2.0/part11
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 11 (of 16)."
  18. # Contents:  kernel_private/src/shell/xv_native.c
  19. #   kernel_private/src/talk/talk.c src/kernel_current/talk/talk.c
  20. # Wrapped by vixie@efficacy.home.vix.com on Sun Apr 25 23:10:43 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'kernel_private/src/shell/xv_native.c' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'kernel_private/src/shell/xv_native.c'\"
  24. else
  25. echo shar: Extracting \"'kernel_private/src/shell/xv_native.c'\" \(24300 characters\)
  26. sed "s/^X//" >'kernel_private/src/shell/xv_native.c' <<'END_OF_FILE'
  27. X/****************************************************************************************
  28. X *                                            *
  29. X * file: xv_native.c                                    *
  30. X *                                            *
  31. X * the xlisp wrappers for the VEOS native prims.                    *
  32. X *                                            *
  33. X * creation: December, 1991                                *
  34. X *                                            *
  35. X *                                            *
  36. X * by Geoffrey P. Coco at the HITLab, Seattle.                          *
  37. X *                                            *
  38. X ****************************************************************************************/
  39. X
  40. X
  41. X
  42. X/****************************************************************************************
  43. X * Copyright (C) 1992  Geoffrey P. Coco, Human Interface Technology Lab, Seattle    *
  44. X ****************************************************************************************/
  45. X
  46. X
  47. X
  48. X/****************************************************************************************
  49. X                      Preliminaries
  50. X ****************************************************************************************/
  51. X
  52. X#include <math.h>
  53. X#include "xlisp.h"
  54. X
  55. X/* VEOS definitions: */
  56. X#include "kernel.h"
  57. X
  58. X#define DEFINE_NATIVE_GLOBS
  59. X#include "xv_native.h"
  60. X#undef DEFINE_NATIVE_GLOBS
  61. X
  62. X/****************************************************************************************/
  63. X
  64. XTVeosErr Native_MessageToLSpace();
  65. Xvoid Native_ShowMatchArgs();
  66. Xvoid Native_ShowSite();
  67. XTVeosErr Native_XCopySiteMatches();
  68. XTVeosErr Native_XRemoveSiteMatches();
  69. XTVeosErr Native_XInsertEltAtSite();
  70. Xvoid Native_NextMsg();
  71. XTVeosErr Native_DoThrow();
  72. X
  73. X/****************************************************************************************/
  74. X
  75. X
  76. X
  77. X/****************************************************************************************
  78. X                 Veos Primitive Wrappers
  79. X ****************************************************************************************/
  80. X
  81. X
  82. X/****************************************************************************************/
  83. XLVAL Native_Init()
  84. X{    
  85. X    LVAL         pXReturn;
  86. X    int        iPort;
  87. X    TVeosErr    iErr;
  88. X    
  89. X    xlsave1(pXReturn);
  90. X
  91. X    if (!moreargs())
  92. X    iPort = TALK_BOGUS_FD;
  93. X    else
  94. X    iPort = getfixnum(xlgafixnum());
  95. X
  96. X    xllastarg();
  97. X
  98. X
  99. X    /** invoke veos kernel inialization **/
  100. X    
  101. X    iErr = Kernel_Init(iPort, Native_MessageToLSpace);
  102. X    if (iErr == VEOS_SUCCESS) {
  103. X
  104. X
  105. X    /** create a lisp based inspace for messages **/
  106. X
  107. X    s_InSpace = xlenter("VEOS_INSPACE");
  108. X    setvalue(s_InSpace, NIL);
  109. X    NATIVE_INSPACE = &getvalue(s_InSpace);
  110. X
  111. X
  112. X    /** create keyword symbols for nancy prims **/
  113. X
  114. X    k_TestTime = xlenter(":TEST-TIME"); /* use with copy only */
  115. X    k_Freq = xlenter(":FREQ");         /* use with copy, put or get */
  116. X
  117. X
  118. X    /** setup invariant matcher settings in global param blocks **/
  119. X
  120. X    Native_InitMatcherPBs();
  121. X
  122. X
  123. X    /** make a uid return value to signify success **/
  124. X
  125. X
  126. X    Uid2XVect(&IDENT_ADDR, &pXReturn);
  127. X    }
  128. X
  129. X
  130. X    xlpop();
  131. X
  132. X
  133. X    return(pXReturn);
  134. X
  135. X    }  /* Native_Init */
  136. X/****************************************************************************************/
  137. X
  138. X
  139. X
  140. X/****************************************************************************************/
  141. XLVAL Native_Close()
  142. X{    
  143. X    if (!KERNEL_INIT)
  144. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  145. X
  146. X    xllastarg();
  147. X
  148. X    Kernel_Shutdown();
  149. X
  150. X    return(true);
  151. X
  152. X    } /* Native_Close */
  153. X/****************************************************************************************/
  154. X
  155. X
  156. X
  157. X/****************************************************************************************/
  158. XLVAL Native_Task()
  159. X{    
  160. X#ifndef OPTIMAL
  161. X    if (!KERNEL_INIT)
  162. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  163. X
  164. X    xllastarg();
  165. X#endif
  166. X
  167. X    /** talk will call our message handler and stuff the inspace **/
  168. X
  169. X    Kernel_SystemTask();
  170. X
  171. X
  172. X    return(true);
  173. X
  174. X    } /* Native_Task */
  175. X/****************************************************************************************/
  176. X
  177. X
  178. X
  179. X
  180. X/****************************************************************************************/
  181. XLVAL Native_Put()
  182. X{
  183. X    TVeosErr    iErr;
  184. X    TTimeStamp    tNow;
  185. X
  186. X#ifndef OPTIMAL
  187. X    if (!KERNEL_INIT)
  188. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  189. X#endif
  190. X
  191. X
  192. X
  193. X    /** get mandatory data argument **/
  194. X
  195. X    native_putPB.pXReplaceElt = xlgetarg();
  196. X
  197. X    
  198. X    
  199. X    /** get pattern from xlisp args **/
  200. X
  201. X    iErr = Native_GetPatternArg(&native_putPB.pPatGr, NANCY_ReplaceMatch);
  202. X    if (iErr != VEOS_SUCCESS)
  203. X    Native_TrapErr(iErr, nil);
  204. X
  205. X
  206. X    /** get optional frequency argument **/
  207. X
  208. X    NATIVE_FREQ_ARG(native_putPB.iFreqFlag);
  209. X
  210. X
  211. X    /** set the data time-stamp **/
  212. X
  213. X    GET_TIME(tNow);
  214. X    native_putPB.pStampTime = &tNow;
  215. X
  216. X
  217. X    /** dispatch the matcher **/
  218. X
  219. X    xlsave1(native_putPB.pXResult);
  220. X    
  221. X    Native_XMandR(&native_putPB);
  222. X
  223. X    xlpop();
  224. X
  225. X
  226. X
  227. X    /** clean up **/
  228. X
  229. X    Nancy_DisposeGrouple(native_putPB.pPatGr);
  230. X
  231. X
  232. X
  233. X    return (native_putPB.pXResult);
  234. X
  235. X    } /* Native_Put */
  236. X/****************************************************************************************/
  237. X
  238. X
  239. X/****************************************************************************************/
  240. XLVAL Native_Get()
  241. X{
  242. X    TVeosErr    iErr;
  243. X
  244. X#ifndef OPTIMAL
  245. X    if (!KERNEL_INIT)
  246. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  247. X#endif
  248. X
  249. X    /** get pattern from xlisp args **/
  250. X
  251. X    iErr = Native_GetPatternArg(&native_getPB.pPatGr, NANCY_RemoveMatch);
  252. X    if (iErr != VEOS_SUCCESS)
  253. X    Native_TrapErr(iErr, nil);
  254. X
  255. X
  256. X    /** get optional frequency argument **/
  257. X
  258. X    NATIVE_FREQ_ARG(native_getPB.iFreqFlag);
  259. X
  260. X
  261. X    /** dispatch the matcher **/
  262. X    
  263. X    xlsave1(native_getPB.pXResult);
  264. X
  265. X    Native_XMandR(&native_getPB);
  266. X
  267. X    xlpop();
  268. X
  269. X
  270. X    /** clean up **/
  271. X
  272. X    Nancy_DisposeGrouple(native_getPB.pPatGr);
  273. X
  274. X
  275. X
  276. X    return (native_getPB.pXResult);
  277. X
  278. X    } /* Native_Get */
  279. X/****************************************************************************************/
  280. X
  281. X
  282. X/****************************************************************************************/
  283. XLVAL Native_Copy()
  284. X{
  285. X    TVeosErr    iErr;
  286. X    TTimeStamp    tTest;
  287. X
  288. X#ifndef OPTIMAL
  289. X    if (!KERNEL_INIT)
  290. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  291. X#endif
  292. X
  293. X
  294. X
  295. X    /** get pattern from xlisp args **/
  296. X
  297. X    iErr = Native_GetPatternArg(&native_copyPB.pPatGr, NANCY_CopyMatch);
  298. X    if (iErr != VEOS_SUCCESS)
  299. X    Native_TrapErr(iErr, nil);
  300. X
  301. X
  302. X    /** look for optional time-stamp-test **/
  303. X
  304. X    NATIVE_TIME_ARG(native_copyPB.pTestTime, tTest);
  305. X
  306. X
  307. X    /** get optional frequency argument **/
  308. X
  309. X    NATIVE_FREQ_ARG(native_copyPB.iFreqFlag);
  310. X
  311. X
  312. X    /** dispatch the matcher **/
  313. X
  314. X    xlsave1(native_copyPB.pXResult);
  315. X    
  316. X    Native_XMandR(&native_copyPB);
  317. X
  318. X    xlpop();
  319. X
  320. X
  321. X    /** clean up **/
  322. X
  323. X    Nancy_DisposeGrouple(native_copyPB.pPatGr);
  324. X
  325. X
  326. X
  327. X    return (native_copyPB.pXResult);
  328. X
  329. X    } /* Native_Copy */
  330. X/****************************************************************************************/
  331. X
  332. X
  333. X/****************************************************************************************/
  334. XLVAL Native_Throw()
  335. X{
  336. X    LVAL    pXData, pXDests;
  337. X    TVeosErr    iErr;
  338. X
  339. X#ifndef OPTIMAL
  340. X    if (!KERNEL_INIT)
  341. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  342. X#endif
  343. X
  344. X    /** get dests argument **/
  345. X
  346. X    pXDests = xlgalist();
  347. X
  348. X
  349. X    /** get data argument **/
  350. X
  351. X    pXData = xlgetarg();
  352. X
  353. X#ifndef OPTIMAL
  354. X    xllastarg();
  355. X#endif
  356. X
  357. X    iErr = Native_DoThrow(pXDests, pXData);
  358. X
  359. X    return(iErr == VEOS_SUCCESS ? true : NIL);
  360. X
  361. X    } /* Native_Throw */
  362. X/****************************************************************************************/
  363. X
  364. X
  365. X
  366. X/****************************************************************************************/
  367. XLVAL Native_Catch()
  368. X{
  369. X    LVAL    pSave;
  370. X    TPElt    pElt;
  371. X
  372. X#ifndef OPTIMAL
  373. X    if (!KERNEL_INIT)
  374. X    Native_TrapErr(NATIVE_NOKERNEL, nil);
  375. X
  376. X    xllastarg();
  377. X#endif
  378. X
  379. X    Native_NextMsg(&pSave);
  380. X
  381. X    return (pSave);
  382. X
  383. X    } /* Native_Catch */
  384. X/****************************************************************************************/
  385. X
  386. X
  387. X
  388. X/****************************************************************************************/
  389. XLVAL Native_MinTime()
  390. X{    
  391. X    TF2L    fTrans;
  392. X    
  393. X    /* guaranteed to be earlier than any system time */
  394. X
  395. X    fTrans.u.l = NANCY_MINTIME;
  396. X
  397. X    return(cvflonum(fTrans.u.f));
  398. X
  399. X    }  /* Native_MinTime */
  400. X/****************************************************************************************/
  401. X
  402. X
  403. X
  404. X/****************************************************************************************/
  405. XLVAL Native_NoSignals()
  406. X{    
  407. X    SIG_ENABLE = FALSE;
  408. X
  409. X    return(true);
  410. X
  411. X    }  /* Native_NoSignals */
  412. X/****************************************************************************************/
  413. X
  414. X
  415. X
  416. X/****************************************************************************************/
  417. XLVAL Native_Bugs()
  418. X{    
  419. X    LVAL    pXModule;
  420. X    char    *sName;
  421. X
  422. X    pXModule = xlgastring();
  423. X    sName = (char *) getstring(pXModule);
  424. X    
  425. X    if (strcmp(sName, "talk") == 0)
  426. X    TALK_BUGS = TALK_BUGS ? FALSE : TRUE;
  427. X
  428. X    else if (strcmp(sName, "nancy") == 0)
  429. X    NANCY_BUGS = NANCY_BUGS ? FALSE : TRUE;
  430. X
  431. X    else if (strcmp(sName, "shell") == 0)
  432. X    SHELL_BUGS = SHELL_BUGS ? FALSE : TRUE;
  433. X
  434. X    return(true);
  435. X
  436. X    }  /* Native_Bugs */
  437. X/****************************************************************************************/
  438. X
  439. Xextern int iEvals;
  440. X
  441. X/****************************************************************************************/
  442. XLVAL Native_Zoot()
  443. X{
  444. X    static int    iAlreadySeen = 0;
  445. X    int        iSinceLast;
  446. X
  447. X    iSinceLast = iEvals - iAlreadySeen;
  448. X    iAlreadySeen = iEvals;
  449. X
  450. X    return(cvfixnum(iSinceLast));
  451. X
  452. X    } /* Native_Zoot */
  453. X/****************************************************************************************/
  454. X
  455. X
  456. X
  457. X
  458. X/****************************************************************************************
  459. X             The Beuractratic Linkage Between Veos and XLISP
  460. X ****************************************************************************************/
  461. X
  462. X
  463. X/****************************************************************************************/
  464. XTVeosErr Shell_LoadNativePrims()
  465. X{
  466. X#define VEOS_NATIVE_LOAD
  467. X#include "xv_native_prims.h"
  468. X#undef VEOS_NATIVE_LOAD
  469. X
  470. X    return(VEOS_SUCCESS);
  471. X    }
  472. X/****************************************************************************************/
  473. X
  474. X
  475. X/****************************************************************************************/
  476. XTVeosErr Shell_BailOut(sErr)
  477. X    char        *sErr;
  478. X{
  479. X
  480. X    xlfatal(sErr);
  481. X
  482. X    /** not reached **/
  483. X
  484. X    return(VEOS_SUCCESS);
  485. X
  486. X    } /* Shell_BailOut */
  487. X/****************************************************************************************/
  488. X
  489. X
  490. X
  491. X/****************************************************************************************
  492. X             The Sticky Goo Just Beneath the Wrappers
  493. X ****************************************************************************************/
  494. X
  495. X
  496. X/****************************************************************************************/
  497. XTVeosErr Native_InitMatcherPBs()
  498. X{
  499. X    /** vget settings **/
  500. X    
  501. X    native_getPB.pSrcGr = WORK_SPACE;
  502. X    native_getPB.iDestroyFlag = NANCY_RemoveMatch;
  503. X    native_getPB.pXReplaceElt = nil;
  504. X    native_getPB.pStampTime = nil;
  505. X    native_getPB.pTestTime = nil;
  506. X    
  507. X    /** vcopy settings **/
  508. X    
  509. X    native_copyPB.pSrcGr = WORK_SPACE;
  510. X    native_copyPB.iDestroyFlag = NANCY_CopyMatch;
  511. X    native_copyPB.pXReplaceElt = nil;
  512. X    native_copyPB.pStampTime = nil;
  513. X
  514. X    /** vput settings **/
  515. X    
  516. X    native_putPB.pSrcGr = WORK_SPACE;
  517. X    native_putPB.iDestroyFlag = NANCY_ReplaceMatch;
  518. X    native_putPB.pTestTime = nil;
  519. X
  520. X
  521. X    return(VEOS_SUCCESS);
  522. X    
  523. X    } /* Native_InitMatcherPBs */
  524. X/****************************************************************************************/
  525. X
  526. X
  527. X
  528. X/****************************************************************************************/
  529. XTVeosErr Native_DoThrow(pXDests, pXData)
  530. X    LVAL    pXData, pXDests;
  531. X{
  532. X    TPUidNode    pDests;
  533. X    TVeosErr    iErr;
  534. X    TMsgRec    msgOut;
  535. X
  536. X
  537. X    /** convert host/port vectors to talk uids **/
  538. X
  539. X    iErr = Native_XVectsToUids(pXDests, &pDests);
  540. X    if (iErr != VEOS_SUCCESS) {
  541. X    Native_TrapErr(iErr, pXDests);
  542. X    }
  543. X
  544. X    /** convert data element to flat network format **/
  545. X
  546. X    iErr = Native_XEltToMsgRec(pXData, &msgOut);
  547. X    if (iErr != VEOS_SUCCESS) {
  548. X    Native_DisposeUids(pDests);
  549. X    Native_TrapErr(iErr, pXData);
  550. X    }
  551. X
  552. X    /** pass the flat message to veos kernel **/
  553. X
  554. X    iErr = Talk_SpeakToMany(pDests, &msgOut);
  555. X
  556. X
  557. X    Native_DisposeUids(pDests);
  558. X
  559. X    return(iErr);
  560. X
  561. X    } /* Native_DoThrow */
  562. X/****************************************************************************************/
  563. X
  564. X
  565. X
  566. X/****************************************************************************************/
  567. Xvoid Native_NextMsg(hMsg)
  568. X    LVAL          *hMsg;
  569. X{
  570. X    *hMsg = NIL;
  571. X
  572. X    if (!null(*NATIVE_INSPACE)) {
  573. X    
  574. X    /** get the oldest message **/
  575. X    
  576. X    *hMsg = car(*NATIVE_INSPACE);
  577. X    
  578. X    /** remove this msg from list immediately. 
  579. X     ** first cons cell in this list will thus be garbage collected. 
  580. X     ** pass back the new msg. 
  581. X     **/ 
  582. X    
  583. X    *NATIVE_INSPACE = cdr(*NATIVE_INSPACE); 
  584. X    }
  585. X    }
  586. X/****************************************************************************************/
  587. X
  588. X
  589. X
  590. X/****************************************************************************************/
  591. XTVeosErr Native_XMandR(pMandRPB)
  592. X    TPXMandRRec        pMandRPB;
  593. X{
  594. X    TVeosErr        iErr;
  595. X    TMatchRec        matchSpec;
  596. X    TPReplaceRec    pSite, pSave;
  597. X
  598. X    
  599. X    /** Initialize the match record.
  600. X     ** This record get passed through the entire match process.
  601. X     ** The matcher uses to record sites for removal and insertion.
  602. X     ** If the matcher returns success,
  603. X     ** we then perform any destructive operations on the gspace.
  604. X     **/
  605. X
  606. X    matchSpec.pPatGr = pMandRPB->pPatGr;
  607. X    matchSpec.pSrcGr = pMandRPB->pSrcGr;
  608. X    matchSpec.iDestroyFlag = pMandRPB->iDestroyFlag;
  609. X    matchSpec.iFreqFlag = pMandRPB->iFreqFlag;
  610. X    matchSpec.pReplaceList = nil;
  611. X    matchSpec.pTouchList = nil;
  612. X
  613. X#ifndef OPTIMAL
  614. X    if (NANCY_BUGS) 
  615. X    Native_ShowMatchArgs(pMandRPB);
  616. X#endif
  617. X
  618. X    /************************************/
  619. X
  620. X    iErr = Nancy_MatchGrouple(&matchSpec);
  621. X
  622. X    /************************************/
  623. X
  624. X#ifndef OPTIMAL
  625. X    if (NANCY_BUGS)
  626. X    fprintf(stderr, "nancy %s: match %s.\n", 
  627. X        WHOAMI, iErr == VEOS_SUCCESS ? "succeeded" : "failed");
  628. X#endif
  629. X        
  630. X    /** Perform any destructive operations on the gspace.
  631. X     ** These occur in on a per-site basis.
  632. X     ** A site is:
  633. X     **   an enclosing grouple,
  634. X     **   a set of element intervals,
  635. X     **   an element index at which to insert.
  636. X     ** Sites are generated by the matcher during matching.
  637. X     **/
  638. X
  639. X    /** perform destructive element retrieval
  640. X     **/
  641. X
  642. X    switch (pMandRPB->iDestroyFlag) {
  643. X
  644. X    case NANCY_CopyMatch:
  645. X    for (pSite = matchSpec.pReplaceList;
  646. X         pSite && iErr == VEOS_SUCCESS;
  647. X         pSite = pSite->pNext) {
  648. X#ifndef OPTIMAL
  649. X        if (NANCY_BUGS) 
  650. X        Native_ShowSite(pSite);
  651. X#endif
  652. X        iErr = Native_XCopySiteMatches(pSite, pMandRPB->pTestTime,
  653. X                       &pMandRPB->pXResult);
  654. X        }
  655. X    break;
  656. X        
  657. X    case NANCY_RemoveMatch:
  658. X    for (pSite = matchSpec.pReplaceList;
  659. X         pSite && iErr == VEOS_SUCCESS;
  660. X         pSite = pSite->pNext) {
  661. X
  662. X#ifndef OPTIMAL
  663. X        if (NANCY_BUGS) 
  664. X        Native_ShowSite(pSite);
  665. X#endif
  666. X        iErr = Native_XRemoveSiteMatches(pSite, pMandRPB->pTestTime,
  667. X                         &pMandRPB->pXResult);
  668. X        }
  669. X    break;
  670. X
  671. X    case NANCY_ReplaceMatch:
  672. X    for (pSite = matchSpec.pReplaceList;
  673. X         pSite && iErr == VEOS_SUCCESS;
  674. X         pSite = pSite->pNext) {
  675. X
  676. X#ifndef OPTIMAL
  677. X        if (NANCY_BUGS) 
  678. X        Native_ShowSite(pSite);
  679. X#endif
  680. X        iErr = Native_XRemoveSiteMatches(pSite, pMandRPB->pTestTime,
  681. X                         &pMandRPB->pXResult);
  682. X        if (iErr == VEOS_SUCCESS)
  683. X        iErr = Native_XInsertEltAtSite(pMandRPB->pXReplaceElt,
  684. X                           pMandRPB->pStampTime, pSite);
  685. X        }
  686. X    break;
  687. X        
  688. X    case NANCY_GimmeMatch:
  689. X    iErr = NANCY_NotSupported;
  690. X    break;
  691. X        
  692. X    } /* switch */
  693. X            
  694. X
  695. X    /** perform destructive element time stamping
  696. X     **/
  697. X
  698. X    if (pMandRPB->pStampTime) {
  699. X
  700. X    for (pSite = matchSpec.pTouchList;
  701. X         pSite && iErr == VEOS_SUCCESS;
  702. X         pSite = pSite->pNext) {
  703. X#ifndef OPTIMAL        
  704. X        if (NANCY_BUGS) 
  705. X        Native_ShowSite(pSite);
  706. X#endif        
  707. X        Native_TouchSiteMatches(pSite, *pMandRPB->pStampTime);
  708. X        
  709. X        }
  710. X    }
  711. X
  712. X    /** free all matcher memory (stays within veos kernel) **/
  713. X
  714. X    pSite = matchSpec.pReplaceList;
  715. X    while (pSite) {
  716. X    pSave = pSite;
  717. X    pSite = pSite->pNext;
  718. X    Shell_ReturnBlock(pSave, sizeof(TReplaceRec), "replace-bp");
  719. X    }
  720. X
  721. X    pSite = matchSpec.pTouchList;
  722. X    while (pSite) {
  723. X    pSave = pSite;
  724. X    pSite = pSite->pNext;
  725. X    Shell_ReturnBlock(pSave, sizeof(TReplaceRec), "replace-bp");
  726. X    }
  727. X    
  728. X
  729. X    if (iErr == VEOS_SUCCESS) {
  730. X
  731. X    /** check for successful insert (give caller appropriate feeback) **/
  732. X
  733. X    if (pMandRPB->iDestroyFlag == NANCY_ReplaceMatch &&
  734. X        pMandRPB->pXResult == NIL)
  735. X
  736. X        pMandRPB->pXResult = true;
  737. X    }
  738. X
  739. X#ifndef OPTIMAL
  740. X    else {
  741. X    if (NANCY_BUGS)
  742. X        Nancy_TrapErr(iErr);
  743. X    }
  744. X#endif
  745. X
  746. X    return(iErr);
  747. X
  748. X    } /* Native_MatchAndReplace */
  749. X/****************************************************************************************/
  750. X
  751. X    
  752. X
  753. X/****************************************************************************************/
  754. XTVeosErr Native_XCopySiteMatches(pSite, pTestTime, hXResult)
  755. X    TPReplaceRec    pSite;
  756. X    TPTimeStamp        pTestTime;
  757. X    LVAL        *hXResult;
  758. X{
  759. X    int            iZone, iToKill, iElt, iLeft, iRight;
  760. X    LVAL        pXElt;
  761. X    TPElt        pVElt;
  762. X    TVeosErr        iErr;
  763. X
  764. X    xlsave1(pXElt);
  765. X
  766. X    /** convert outgoing data into supplanted language format.
  767. X     ** lisp is the current control language
  768. X     **/
  769. X    
  770. X    if (pTestTime == nil) {
  771. X    
  772. X    for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
  773. X        iLeft = pSite->pWipeList[iZone].iLeft;
  774. X        iRight = pSite->pWipeList[iZone].iRight;
  775. X        iToKill = iRight - iLeft + 1;
  776. X
  777. X#ifndef OPTIMAL        
  778. X        if (NANCY_BUGS) {
  779. X        fprintf(stderr, "nancy %s: left: %d right: %d\n",
  780. X            WHOAMI, iLeft, iRight);
  781. X        }
  782. X#endif        
  783. X        for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
  784. X         iElt >= iLeft;
  785. X         iElt--, pVElt --) {
  786. X
  787. X        if (Native_VEltToXElt(pVElt, &pXElt) == VEOS_SUCCESS)
  788. X            
  789. X            /** assume caller protected *hXResult **/
  790. X            *hXResult = cons(pXElt, *hXResult);
  791. X        }
  792. X        }
  793. X    }
  794. X    else {
  795. X
  796. X    for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
  797. X        iLeft = pSite->pWipeList[iZone].iLeft;
  798. X        iRight = pSite->pWipeList[iZone].iRight;
  799. X        iToKill = iRight - iLeft + 1;
  800. X
  801. X#ifndef OPTIMAL
  802. X        if (NANCY_BUGS) {
  803. X        fprintf(stderr, "nancy %s: left: %d right: %d\n",
  804. X            WHOAMI, iLeft, iRight);
  805. X        }
  806. X#endif    
  807. X
  808. X        for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
  809. X         iElt >= iLeft;
  810. X         iElt--, pVElt--) {
  811. X        
  812. X        iErr = Native_NewVEltToXElt(pVElt, &pXElt, *pTestTime);
  813. X        if (iErr == VEOS_SUCCESS) {
  814. X
  815. X            /** assume caller protected *hXResult **/
  816. X            *hXResult = cons(pXElt, *hXResult);
  817. X            }
  818. X        /*
  819. X        else if (iErr == NATIVE_STALE)
  820. X            iErr = VEOS_SUCCESS;
  821. X            */
  822. X        }
  823. X        }
  824. X    }
  825. X
  826. X    xlpop();
  827. X
  828. X    return(VEOS_SUCCESS);
  829. X
  830. X    } /* Native_XCopySiteMatches */
  831. X/****************************************************************************************/
  832. X
  833. X
  834. X
  835. X/****************************************************************************************/
  836. XTVeosErr Native_XRemoveSiteMatches(pSite, pTestTime, hXResult)
  837. X    TPReplaceRec    pSite;
  838. X    TPTimeStamp        pTestTime;
  839. X    LVAL        *hXResult;
  840. X{
  841. X    int            iZone, iToKill, iElt, iLeft, iRight;
  842. X    LVAL        pXElt;
  843. X    TPElt        pVElt;
  844. X
  845. X    xlsave1(pXElt);
  846. X
  847. X    for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
  848. X    iLeft = pSite->pWipeList[iZone].iLeft;
  849. X    iRight = pSite->pWipeList[iZone].iRight;
  850. X    iToKill = iRight - iLeft + 1;
  851. X    
  852. X    /** convert outgoing data into supplanted language format.
  853. X     ** that format is xlisp, and in reverse order
  854. X     **/
  855. X    
  856. X    for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
  857. X         iElt >= iLeft;
  858. X         iElt--, pVElt--) {
  859. X
  860. X        if (Native_VEltToXElt(pVElt, &pXElt) == VEOS_SUCCESS)
  861. X
  862. X        /** assume caller has protected *hXResult **/
  863. X
  864. X        *hXResult = cons(pXElt, *hXResult);
  865. X        }
  866. X    
  867. X    Nancy_DeleteElementsInGrouple(pSite->pEnviron,
  868. X                      iLeft,
  869. X                      iToKill);
  870. X    }
  871. X
  872. X    xlpop();
  873. X
  874. X    return(VEOS_SUCCESS);
  875. X
  876. X    } /* Native_XRemoveSiteMatches */
  877. X/****************************************************************************************/
  878. X
  879. X
  880. X
  881. X/****************************************************************************************/
  882. XTVeosErr Native_XInsertEltAtSite(pXReplaceElt, pStampTime, pSite)
  883. X    LVAL        pXReplaceElt;
  884. X    TPTimeStamp        pStampTime;
  885. X    TPReplaceRec    pSite;
  886. X{
  887. X    TElt        localElt;
  888. X    TVeosErr        iErr = VEOS_SUCCESS;
  889. X
  890. X    if (pSite->iInsertElt >= 0) {
  891. X    
  892. X    localElt = NIL_ELT;
  893. X
  894. X    if (pStampTime)
  895. X        iErr = Native_XEltToNewVElt(pXReplaceElt, &localElt, *pStampTime);
  896. X    else
  897. X        iErr = Native_XEltToVElt(pXReplaceElt, &localElt);
  898. X
  899. X    if (iErr == VEOS_SUCCESS) {
  900. X
  901. X        Nancy_NewElementsInGrouple(pSite->pEnviron, pSite->iInsertElt, 1,
  902. X                       GR_unspecified, 0);
  903. X        pSite->pEnviron->pEltList[pSite->iInsertElt] = localElt;
  904. X        }
  905. X    }
  906. X
  907. X    return(iErr);
  908. X    
  909. X    } /* Native_XInsertEltAtSite */
  910. X/****************************************************************************************/
  911. X
  912. X
  913. X
  914. X/****************************************************************************************/
  915. XTVeosErr Native_TouchSiteMatches(pSite, time)
  916. X    TPReplaceRec    pSite;
  917. X    TTimeStamp        time;
  918. X{
  919. X    int            iZone, iElt, iLeft, iRight;
  920. X    TPElt        pVElt;
  921. X
  922. X    for (iZone = pSite->iZones - 1; iZone >= 0; iZone --) {
  923. X
  924. X    iLeft = pSite->pWipeList[iZone].iLeft;
  925. X    iRight = pSite->pWipeList[iZone].iRight;
  926. X    
  927. X    /** simply update time stamp of given elements **/
  928. X    
  929. X    for (iElt = iRight, pVElt = &pSite->pEnviron->pEltList[iRight];
  930. X         iElt >= iLeft; 
  931. X         iElt--, pVElt--)
  932. X
  933. X        pVElt->tLastMod = time;
  934. X    }
  935. X
  936. X    return(VEOS_SUCCESS);
  937. X
  938. X    } /* Native_TouchSiteMatches */
  939. X/****************************************************************************************/
  940. X
  941. X
  942. X
  943. X/****************************************************************************************/
  944. XTVeosErr Native_MessageToLSpace(pMsgRec)
  945. X    TPMsgRec        pMsgRec;
  946. X{
  947. X    TVeosErr         iErr;
  948. X    LVAL        pXElt, *hFinger;
  949. X    int            iLen;
  950. X    char        *pBuf;
  951. X
  952. X
  953. X    xlsave1(pXElt);
  954. X
  955. X    /** return data to grouple form **/            
  956. X    
  957. X    pBuf = pMsgRec->sMessage;
  958. X    iLen = 0;
  959. X    iErr = Native_MessageToXElt(pBuf, &pXElt, &iLen);
  960. X    
  961. X#ifndef OPTIMAL    
  962. X    if (TALK_BUGS) {
  963. X    fprintf(stderr, "listen %s: results of message conversion, native: %d\n",
  964. X        WHOAMI, iErr);
  965. X    }    
  966. X#endif
  967. X    
  968. X    if (iErr == VEOS_SUCCESS) {
  969. X
  970. X#ifndef OPTIMAL    
  971. X    if (TALK_BUGS) {
  972. X        fprintf(stderr, "listen %s: element in message:\n", WHOAMI);
  973. X
  974. X        errprint(pXElt);
  975. X        }
  976. X#endif
  977. X
  978. X    /** append message to native inspace list **/
  979. X    
  980. X    hFinger = NATIVE_INSPACE;
  981. X    while (!null(*hFinger))
  982. X        hFinger = &cdr(*hFinger);
  983. X
  984. X    *hFinger = cons(pXElt, NIL);
  985. X    }
  986. X
  987. X    xlpop();
  988. X
  989. X    return(iErr);
  990. X
  991. X    } /* Native_MessageToLSpace */
  992. X/****************************************************************************************/
  993. X
  994. X
  995. X
  996. X/****************************************************************************************/
  997. Xvoid Native_ShowMatchArgs(pMandRPB)
  998. X    TPXMandRRec        pMandRPB;
  999. X{
  1000. X    fprintf(stderr, "nancy %s: MandR arguments.\n", WHOAMI);
  1001. X
  1002. X    fprintf(stderr, "nancy %s: source:\n", WHOAMI);
  1003. X    Nancy_GroupleToStream(pMandRPB->pSrcGr, stderr);
  1004. X
  1005. X    fprintf(stderr, "nancy %s: pattern:\n", WHOAMI);
  1006. X    Nancy_GroupleToStream(pMandRPB->pPatGr, stderr);
  1007. X    
  1008. X    fprintf(stderr, "nancy %s: destroyFlag: %s\n", WHOAMI,
  1009. X        pMandRPB->iDestroyFlag == NANCY_RemoveMatch ? "remove" :
  1010. X        pMandRPB->iDestroyFlag == NANCY_CopyMatch ? "copy" :
  1011. X        pMandRPB->iDestroyFlag == NANCY_ReplaceMatch ? "replace" : "unknown");
  1012. X    
  1013. X    fprintf(stderr, "nancy %s: freqFlag: %s\n", WHOAMI,
  1014. X        pMandRPB->iFreqFlag == NANCY_MatchOne ? "one" : "all");
  1015. X    
  1016. X    fprintf(stderr, "nancy %s: replace elt:\n", WHOAMI);
  1017. X    errprint(pMandRPB->pXReplaceElt);
  1018. X    
  1019. X    fprintf(stderr, "nancy %s: stamp-time: ", WHOAMI);
  1020. X    if (pMandRPB->pStampTime)
  1021. X    PRINT_TIME(*pMandRPB->pStampTime, stderr);
  1022. X    else
  1023. X    fprintf(stderr, "nil");
  1024. X    fprintf(stderr, "\n");
  1025. X
  1026. X    fprintf(stderr, "nancy %s: test-time: ", WHOAMI);
  1027. X    if (pMandRPB->pTestTime)
  1028. X    PRINT_TIME(*pMandRPB->pTestTime, stderr);
  1029. X    else
  1030. X    fprintf(stderr, "nil");
  1031. X    fprintf(stderr, "\n");
  1032. X
  1033. X    } 
  1034. X/****************************************************************************************/
  1035. X
  1036. X
  1037. X
  1038. X/****************************************************************************************/
  1039. Xvoid Native_ShowSite(pSite)
  1040. X    TPReplaceRec           pSite;
  1041. X{
  1042. X    fprintf(stderr, "nancy %s: site grouple:\n", WHOAMI);
  1043. X    Nancy_GroupleToStream(pSite->pEnviron, stderr);
  1044. X    fprintf(stderr, "nancy %s: site zones: %d\n", WHOAMI, pSite->iZones);
  1045. X    fprintf(stderr, "nancy %s: site insert elt: %d\n", WHOAMI, pSite->iInsertElt);
  1046. X    }
  1047. X/****************************************************************************************/
  1048. X
  1049. X
  1050. X
  1051. END_OF_FILE
  1052. if test 24300 -ne `wc -c <'kernel_private/src/shell/xv_native.c'`; then
  1053.     echo shar: \"'kernel_private/src/shell/xv_native.c'\" unpacked with wrong size!
  1054. fi
  1055. # end of 'kernel_private/src/shell/xv_native.c'
  1056. fi
  1057. if test -f 'kernel_private/src/talk/talk.c' -a "${1}" != "-c" ; then 
  1058.   echo shar: Will not clobber existing file \"'kernel_private/src/talk/talk.c'\"
  1059. else
  1060. echo shar: Extracting \"'kernel_private/src/talk/talk.c'\" \(24919 characters\)
  1061. sed "s/^X//" >'kernel_private/src/talk/talk.c' <<'END_OF_FILE'
  1062. X/****************************************************************************************
  1063. X *                                            *
  1064. X * file: talk.c                                        *
  1065. X *                                            *
  1066. X * October 20, 1990: an entity's network interface to other entities.                   *
  1067. X *                                            *
  1068. X *             this library represents the presentation & session layers of the    *
  1069. X *             ISO network systems model.                        *
  1070. X *                                            *
  1071. X *                   the network and transport layers provided by socket.c        *
  1072. X *                                            *
  1073. X * by Geoffrey P. Coco at the HITLab, Seattle.                          *
  1074. X *                                            *
  1075. X ****************************************************************************************/
  1076. X
  1077. X
  1078. X/****************************************************************************************
  1079. X * Copyright (C) 1992  Geoffrey P. Coco, Human Interface Technology Lab, Seattle    *
  1080. X ****************************************************************************************/
  1081. X
  1082. X
  1083. X/****************************************************************************************
  1084. X                      Preliminaries
  1085. X ****************************************************************************************/
  1086. X
  1087. X#include "kernel.h"
  1088. X#include "errno.h"
  1089. X#include "sys/signal.h"
  1090. X
  1091. X/****************************************************************************************/
  1092. X
  1093. XTVeosErr Talk_DummyMsgHandler();
  1094. X
  1095. X/****************************************************************************************/
  1096. X
  1097. X
  1098. X
  1099. X/****************************************************************************************
  1100. X * Talk_HelloTalk                                    *
  1101. X *                                            *
  1102. X * talk initialization.  call Talk_HelloTalk() once, and don't proceed upon failure.    */
  1103. X
  1104. XTVeosErr Talk_HelloTalk(iPort, pMessFun)
  1105. X    int            iPort;
  1106. X    TVeosErr        (*pMessFun) ();
  1107. X{
  1108. X    TVeosErr        iErr;
  1109. X    
  1110. X
  1111. X    /** allocate fast message buffers **/
  1112. X    
  1113. X    iErr = VEOS_MEM_ERR;
  1114. X    if (NEWPTR(TALK_BUFFER, char *, TALK_MAX_BUFFER)) {
  1115. X    
  1116. X
  1117. X    /** initialize cache settings **/
  1118. X    
  1119. X    SPEAK_SET = nil;
  1120. X    
  1121. X    LISTEN_SOCKETFD = TALK_BOGUS_FD;
  1122. X    LISTEN_SET = nil;
  1123. X    
  1124. X    FD_ZERO(&OPEN_READ_SOCKETS);
  1125. X    FD_ZERO(&OPEN_WRITE_SOCKETS);
  1126. X    
  1127. X    TALK_MSG_FUNC = pMessFun ? pMessFun : Talk_DummyMsgHandler;
  1128. X    
  1129. X    bzero(SOCK_HOSTS, 26 * sizeof(TPHostNode));
  1130. X    
  1131. X    
  1132. X    /** initialize public cache settings **/
  1133. X    
  1134. X    SPEAK_DIRTY = FALSE;
  1135. X    
  1136. X    
  1137. X    
  1138. X    /** initialize listen connection **/
  1139. X    
  1140. X    iErr = Talk_OpenPort(iPort);
  1141. X    }
  1142. X    
  1143. X    return(iErr);
  1144. X    
  1145. X    } /* Talk_HelloTalk */
  1146. X/****************************************************************************************/
  1147. X
  1148. X
  1149. X
  1150. X
  1151. X/****************************************************************************************
  1152. X * Talk_ByeTalk                                        *
  1153. X *                                             *
  1154. X * cleanup network and memory allocation only after finished using talk library.    */
  1155. X
  1156. XTVeosErr Talk_ByeTalk()
  1157. X{
  1158. X    TPSpeakNode            pSpeakFinger, pTempSpeak;
  1159. X    TPListenNode        pListenFinger, pTempListen;
  1160. X
  1161. X    /** take down listen port **/
  1162. X    
  1163. X    Talk_ClosePort();
  1164. X    
  1165. X    
  1166. X    /** close all speak connections **/
  1167. X    
  1168. X    pSpeakFinger = SPEAK_SET;
  1169. X    while (pSpeakFinger) {
  1170. X    
  1171. X    pTempSpeak = pSpeakFinger->pLink;
  1172. X    
  1173. X    Talk_KillSpeakConnection(pSpeakFinger);
  1174. X    
  1175. X    pSpeakFinger = pTempSpeak;
  1176. X    }
  1177. X    
  1178. X    
  1179. X    /** close listen connections (normal mechanism is while attempting to read) **/
  1180. X    
  1181. X    pListenFinger = LISTEN_SET;
  1182. X    while (pListenFinger) {
  1183. X    
  1184. X    pTempListen = pListenFinger->pLink;
  1185. X    
  1186. X    Talk_KillListenConnection(pListenFinger);
  1187. X    
  1188. X    pListenFinger = pTempListen;
  1189. X    }
  1190. X
  1191. X    
  1192. X    /** deallocate local library cache **/
  1193. X    
  1194. X    if (TALK_BUFFER)
  1195. X    DUMP(TALK_BUFFER);
  1196. X    
  1197. X    
  1198. X    return(VEOS_SUCCESS);
  1199. X    
  1200. X    } /* Talk_ByeTalk */
  1201. X/****************************************************************************************/
  1202. X
  1203. X
  1204. X
  1205. X/****************************************************************************************/
  1206. XTVeosErr Talk_SpeakToMany(pDests, pMsg)
  1207. X    TPUidNode        pDests;
  1208. X    TPMsgRec        pMsg;
  1209. X{
  1210. X    TVeosErr        iErr;
  1211. X    TPUidNode        pFinger;
  1212. X
  1213. X    iErr = VEOS_FAILURE;
  1214. X
  1215. X    if (pDests && pMsg) {
  1216. X
  1217. X    iErr = VEOS_SUCCESS;
  1218. X
  1219. X    pFinger = pDests;
  1220. X    while (pFinger && iErr == VEOS_SUCCESS) {
  1221. X
  1222. X        iErr = Talk_PostSpeakMessage(&pFinger->addr, pMsg);
  1223. X
  1224. X        pFinger = pFinger->pNext;
  1225. X        }
  1226. X    }
  1227. X
  1228. X    return(iErr);
  1229. X
  1230. X    } /* Talk_SpeakToMany */
  1231. X/****************************************************************************************/
  1232. X
  1233. X
  1234. X
  1235. X/****************************************************************************************
  1236. X *                     private functions                    *
  1237. X ****************************************************************************************/
  1238. X
  1239. X
  1240. X/****************************************************************************************
  1241. X * Talk_OpenPort                                    *
  1242. X *                                            *
  1243. X * establish an incoming message gateway for the entity client.                *
  1244. X * Talk_OpenPort() should be paired with a call to Talk_ClosePort().            */
  1245. X
  1246. XTVeosErr Talk_OpenPort(iPort)
  1247. X    int            iPort;
  1248. X{
  1249. X    TVeosErr        iErr;
  1250. X    boolean        bFound;
  1251. X
  1252. X    
  1253. X    /** install entity connection handler **/
  1254. X/*
  1255. X    signal(SIGIO, Talk_ConnectTrap);
  1256. X*/
  1257. X    
  1258. X    
  1259. X    /** initiate network comminication. alert world of our existence. **/
  1260. X
  1261. X    if (TALK_BUGS)
  1262. X    fprintf(stderr, "listen %s: trying to listen...\n", WHOAMI);
  1263. X
  1264. X
  1265. X    if (iPort != TALK_BOGUS_PORT) {
  1266. X    
  1267. X    /** use chosen port number **/
  1268. X    
  1269. X    iErr = Sock_Listen(&LISTEN_SOCKETFD,
  1270. X                     iPort,
  1271. X                     "tcp",
  1272. X                     TALK_AGRESSIVE);
  1273. X    }
  1274. X    else {
  1275. X    /** try all sockets until we find an unused one **/
  1276. X    
  1277. X    iPort = TALK_MIN_PORT;
  1278. X    iErr = VEOS_FAILURE;
  1279. X    
  1280. X    while (iErr != VEOS_SUCCESS &&
  1281. X           iPort < TALK_MAX_PORT) {
  1282. X        
  1283. X        iErr = Sock_Listen(&LISTEN_SOCKETFD,
  1284. X                     iPort,
  1285. X                     "tcp",
  1286. X                     TALK_PASSIVE);
  1287. X        if (iErr != VEOS_SUCCESS)
  1288. X        iPort ++;
  1289. X        }
  1290. X    }
  1291. X    
  1292. X    
  1293. X    if (iErr != VEOS_SUCCESS) {
  1294. X    if (TALK_BUGS)
  1295. X        fprintf(stderr, "listen %s: cannot listen, talk: %d, sys: %d\n",
  1296. X            WHOAMI,  iErr, errno);
  1297. X    }
  1298. X
  1299. X    else {
  1300. X    /** maintain references to entity uid **/
  1301. X    
  1302. X    IDENT_ADDR.iPort = iPort;
  1303. X    Shell_UpdateUid();
  1304. X
  1305. X    if (TALK_BUGS)
  1306. X        fprintf(stderr, "listen %s: successful listen\n", WHOAMI);
  1307. X
  1308. X
  1309. X    /** setup shared memory channel **/
  1310. X
  1311. X    iErr = ShMem_Init();
  1312. X    }
  1313. X
  1314. X    return(iErr);
  1315. X    
  1316. X    } /* Talk_OpenPort */
  1317. X/****************************************************************************************/
  1318. X
  1319. X
  1320. X
  1321. X/****************************************************************************************
  1322. X * Talk_ClosePort                                    *
  1323. X *                                                   *
  1324. X * close the incoming message gateway.  the cleanup counterpart to Talk_OpenTalk().    */
  1325. X
  1326. XTVeosErr Talk_ClosePort()
  1327. X{
  1328. X    TVeosErr        iErr;
  1329. X    
  1330. X
  1331. X    /** unregister ourselves from net **/
  1332. X    
  1333. X    if (TALK_BUGS)
  1334. X    fprintf(stderr, "listen %s: about to close main listen socket: %d, sys: %d\n",
  1335. X        WHOAMI, LISTEN_SOCKETFD, errno);
  1336. X    
  1337. X
  1338. X    iErr = Sock_Close(&LISTEN_SOCKETFD);
  1339. X    
  1340. X    if (TALK_BUGS)
  1341. X    fprintf(stderr, "listen %s: closed main listen port, talk: %d, sys: %d\n",
  1342. X        WHOAMI, iErr, errno);
  1343. X
  1344. X
  1345. X    /** takedown shared memory channel **/
  1346. X    
  1347. X    ShMem_Close();
  1348. X
  1349. X
  1350. X    return(iErr);
  1351. X    
  1352. X    } /* Talk_ClosePort */
  1353. X/****************************************************************************************/
  1354. X
  1355. X
  1356. X
  1357. X
  1358. X/****************************************************************************************/
  1359. XTVeosErr Talk_GatherListenMessages()
  1360. X{
  1361. X    TVeosErr           iErr;
  1362. X    int            iSocketFD;
  1363. X    THListenNode    hListenFinger;
  1364. X    TPListenNode        pSaveLink;
  1365. X    
  1366. X    
  1367. X    hListenFinger = &LISTEN_SET;
  1368. X    
  1369. X    while (*hListenFinger) {
  1370. X
  1371. X    pSaveLink = *hListenFinger;
  1372. X    iSocketFD = (*hListenFinger)->iSocketFD;
  1373. X    
  1374. X
  1375. X    /** attempt to read messages from the connection **/
  1376. X    
  1377. X    iErr = Talk_RetrieveMessages(iSocketFD);
  1378. X    if (iErr != TALK_CONN_CLOSED)
  1379. X        
  1380. X        hListenFinger = &(*hListenFinger)->pLink;        
  1381. X    
  1382. X    
  1383. X    else {
  1384. X        /** connection was lost from other end **/
  1385. X
  1386. X        if (TALK_BUGS)
  1387. X        fprintf(stderr, "listen %s: lost connection on socket: %d\n",
  1388. X            WHOAMI, iSocketFD);
  1389. X
  1390. X        pSaveLink = (*hListenFinger)->pLink;
  1391. X        
  1392. X        Talk_KillListenConnection(*hListenFinger);
  1393. X        
  1394. X        *hListenFinger = pSaveLink;
  1395. X        }
  1396. X    }
  1397. X
  1398. X
  1399. X    /** all shared memory messages come in through one channel **/
  1400. X    
  1401. X    ShMem_GatherMessages();
  1402. X
  1403. X
  1404. X    return(iErr);
  1405. X    
  1406. X    } /* Talk_GatherListenMessages */
  1407. X/****************************************************************************************/
  1408. X
  1409. X
  1410. X
  1411. X
  1412. X/****************************************************************************************
  1413. X * Talk_EstNewListenConnections                                */
  1414. X
  1415. XTVeosErr Talk_EstNewListenConnections()
  1416. X{
  1417. X    TVeosErr        iErr = VEOS_SUCCESS;
  1418. X    TPListenNode    pNewNode;
  1419. X    
  1420. X    iErr = Talk_NewListenConnection(LISTEN_SOCKETFD, &pNewNode);
  1421. X    if (iErr == VEOS_SUCCESS) {
  1422. X    
  1423. X    /** store this record locally **/
  1424. X    
  1425. X    pNewNode->pLink = LISTEN_SET;
  1426. X    LISTEN_SET = pNewNode;
  1427. X    }
  1428. X
  1429. X    return(VEOS_SUCCESS);
  1430. X    
  1431. X    } /* Talk_EstNewListenConnections */
  1432. X/****************************************************************************************/
  1433. X
  1434. X
  1435. X
  1436. X/****************************************************************************************/
  1437. XTVeosErr Talk_DispatchQedSpeakMessages()
  1438. X{
  1439. X    TVeosErr        iErr;
  1440. X    THSpeakNode        hSpeakFinger;
  1441. X    TPSpeakNode        pSaveLink;
  1442. X    boolean        bLocalDirty;
  1443. X    
  1444. X    iErr = VEOS_SUCCESS;
  1445. X    
  1446. X
  1447. X    /** inspect every open connection for queued outgoing messages **/
  1448. X    
  1449. X    hSpeakFinger = &SPEAK_SET;
  1450. X    SPEAK_DIRTY = FALSE;
  1451. X    
  1452. X    while (*hSpeakFinger) {
  1453. X    
  1454. X    
  1455. X    /** attempt to send queued messages for this connection in order **/
  1456. X    
  1457. X    iErr = Talk_ThrowMessages(*hSpeakFinger, &bLocalDirty);
  1458. X    if (iErr == TALK_CONN_CLOSED) {
  1459. X        
  1460. X        
  1461. X        /** connection was lost from other end **/
  1462. X
  1463. X        if (TALK_BUGS)
  1464. X        fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
  1465. X            WHOAMI,
  1466. X            (*hSpeakFinger)->destRec.lHost,
  1467. X            (*hSpeakFinger)->destRec.iPort,
  1468. X            (*hSpeakFinger)->iSocketFD);
  1469. X        
  1470. X        pSaveLink = (*hSpeakFinger)->pLink;
  1471. X        
  1472. X        Talk_KillSpeakConnection(*hSpeakFinger);
  1473. X        
  1474. X        *hSpeakFinger = pSaveLink;
  1475. X        }
  1476. X    
  1477. X    else {
  1478. X        if (bLocalDirty)
  1479. X        SPEAK_DIRTY = TRUE;
  1480. X        
  1481. X        
  1482. X        /** check next connection **/
  1483. X        
  1484. X        hSpeakFinger = &(*hSpeakFinger)->pLink;        
  1485. X        }
  1486. X    }
  1487. X
  1488. X    return(iErr);
  1489. X    
  1490. X    } /* Talk_DispatchQedSpeakMessages */
  1491. X/****************************************************************************************/
  1492. X
  1493. X
  1494. X
  1495. X
  1496. X/****************************************************************************************
  1497. X * Talk_NewListenConnection                                */
  1498. X
  1499. XTVeosErr Talk_NewListenConnection(iListenSocketFD, hListenNode)
  1500. X    int            iListenSocketFD;
  1501. X    THListenNode    hListenNode;
  1502. X{
  1503. X    TPListenNode    pNewNode;
  1504. X    TVeosErr        iErr;
  1505. X    int            iSocketFD;
  1506. X    
  1507. X    
  1508. X    iErr = Sock_ReadSelect(iListenSocketFD);
  1509. X    if (iErr == VEOS_SUCCESS) {    
  1510. X
  1511. X    if (TALK_BUGS)
  1512. X        fprintf(stderr, "listen %s: another entity is trying to connect...\n",
  1513. X            WHOAMI);
  1514. X    
  1515. X    /** establish a full-duplex connection **/
  1516. X    
  1517. X    iErr = Sock_Accept(iListenSocketFD, &iSocketFD);
  1518. X    
  1519. X    if (iErr != VEOS_SUCCESS)
  1520. X        perror("talk: _Accept");
  1521. X    
  1522. X    else {
  1523. X
  1524. X        if (TALK_BUGS)
  1525. X        fprintf(stderr, "listen %s: another entity connected on socket: %d\n",
  1526. X            WHOAMI, iSocketFD);
  1527. X
  1528. X        /** allocate listen connection record **/
  1529. X        
  1530. X        iErr = Shell_NewBlock(sizeof(TListenNode), &pNewNode, "listen node");
  1531. X        if (iErr != VEOS_SUCCESS) {
  1532. X
  1533. X        Sock_Close(&iSocketFD);
  1534. X        }
  1535. X        
  1536. X        else {
  1537. X        /** setup connection record **/
  1538. X        
  1539. X        pNewNode->iSocketFD = iSocketFD;
  1540. X        pNewNode->pLink = nil;
  1541. X        
  1542. X        *hListenNode = pNewNode;
  1543. X        }
  1544. X        }
  1545. X    }
  1546. X    
  1547. X    return(iErr);
  1548. X    
  1549. X    } /* Talk_NewListenConnection */
  1550. X/****************************************************************************************/
  1551. X
  1552. X
  1553. X
  1554. X
  1555. X/****************************************************************************************/
  1556. XTVeosErr Talk_KillListenConnection(pDeadNode)
  1557. X    TPListenNode    pDeadNode;
  1558. X{
  1559. X    TVeosErr        iErr;
  1560. X    
  1561. X    iErr = VEOS_FAILURE;
  1562. X    
  1563. X    if (pDeadNode) {            /* sane? */
  1564. X    
  1565. X    if (TALK_BUGS) 
  1566. X        fprintf(stderr, "listen %s: closing connection on socket: %d\n",
  1567. X            WHOAMI, pDeadNode->iSocketFD);
  1568. X    
  1569. X    /** strike this connection in all respects **/
  1570. X    
  1571. X        iErr = Sock_Close(&pDeadNode->iSocketFD);
  1572. X
  1573. X
  1574. X    if (TALK_BUGS)
  1575. X        fprintf(stderr, "listen %s: closed listen connection, talk: %d, sys: %d\n",
  1576. X            WHOAMI, iErr, errno);
  1577. X
  1578. X
  1579. X    Shell_ReturnBlock(pDeadNode, sizeof(TListenNode), "listen node");
  1580. X    
  1581. X    iErr = VEOS_SUCCESS;
  1582. X    }
  1583. X    
  1584. X    return(iErr);
  1585. X    
  1586. X    } /* Talk_KillListenConnection */
  1587. X/****************************************************************************************/
  1588. X
  1589. X
  1590. X
  1591. X/****************************************************************************************/
  1592. XTVeosErr Talk_PostSpeakMessage(pDest, pMsgBlock)
  1593. X    TPUid        pDest;
  1594. X    TPMsgRec        pMsgBlock;
  1595. X{
  1596. X    TVeosErr        iErr;
  1597. X    TPSpeakNode        pDestNode, pSaveLink;
  1598. X    THSpeakNode        hFinger;
  1599. X    boolean        bLocalDirty;
  1600. X
  1601. X    if (pDest) {
  1602. X
  1603. X
  1604. X    /** do we already have a connection to this destination? **/
  1605. X    
  1606. X    hFinger = &SPEAK_SET;
  1607. X    iErr = VEOS_FAILURE;
  1608. X    
  1609. X    while (*hFinger && iErr != VEOS_SUCCESS) {
  1610. X        
  1611. X        if (UID_COMPARE(&(*hFinger)->destRec, pDest)) {
  1612. X        
  1613. X        pDestNode = *hFinger;
  1614. X        iErr = VEOS_SUCCESS;
  1615. X        }
  1616. X        else
  1617. X        hFinger = &(*hFinger)->pLink;        
  1618. X        }
  1619. X    
  1620. X    
  1621. X    /** attempt to connect to this destaination for the first time **/
  1622. X    
  1623. X    if (iErr != VEOS_SUCCESS) {
  1624. X        iErr = Talk_NewSpeakConnection(pDest,
  1625. X                           &pDestNode);
  1626. X        if (iErr == VEOS_SUCCESS) {
  1627. X        
  1628. X        /** add connection record to local list **/
  1629. X        
  1630. X        pDestNode->pLink = SPEAK_SET;
  1631. X        SPEAK_SET = pDestNode;
  1632. X        hFinger = &SPEAK_SET;
  1633. X        }
  1634. X        }
  1635. X    
  1636. X    
  1637. X    /** add new message to this connection's queue **/
  1638. X    
  1639. X    if (iErr == VEOS_SUCCESS) {
  1640. X        iErr = Talk_AddSpeakJob(pDestNode, pMsgBlock); 
  1641. X        if (iErr == VEOS_SUCCESS) {
  1642. X        
  1643. X        
  1644. X        /** attempt to send this message right now **/
  1645. X        
  1646. X        iErr = Talk_ThrowMessages(pDestNode, &bLocalDirty);
  1647. X        if (iErr == TALK_CONN_CLOSED) {
  1648. X            
  1649. X            
  1650. X            /** connection was lost from other end **/
  1651. X
  1652. X            if (TALK_BUGS)
  1653. X            fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
  1654. X                WHOAMI,
  1655. X                pDestNode->destRec.lHost,
  1656. X                pDestNode->destRec.iPort,
  1657. X                pDestNode->iSocketFD);
  1658. X
  1659. X            
  1660. X            pSaveLink = pDestNode->pLink;
  1661. X            
  1662. X            Talk_KillSpeakConnection(pDestNode);
  1663. X            
  1664. X            *hFinger = pSaveLink;
  1665. X            }
  1666. X
  1667. X        else if (bLocalDirty)
  1668. X            SPEAK_DIRTY = TRUE;
  1669. X        }
  1670. X        }
  1671. X    }
  1672. X
  1673. X    return(iErr);
  1674. X    
  1675. X    } /* Talk_PostSpeakMessage */
  1676. X/****************************************************************************************/
  1677. X
  1678. X
  1679. X
  1680. X/****************************************************************************************
  1681. X * Talk_NewSpeakConnection                                */
  1682. X
  1683. XTVeosErr Talk_NewSpeakConnection(pDest, hSpeakNode)
  1684. X    TPUid        pDest;
  1685. X    THSpeakNode        hSpeakNode;
  1686. X{
  1687. X    TPSpeakNode        pNewNode;
  1688. X    int            iSocketFD;
  1689. X    TPSharedRec        pChannel;
  1690. X    TVeosErr        iErr;
  1691. X    boolean        bSharedMem;
  1692. X
  1693. X    *hSpeakNode = nil;
  1694. X    
  1695. X    
  1696. X    /** try to connect to destination shell **/
  1697. X
  1698. X    if (TALK_BUGS)    
  1699. X    fprintf(stderr, "speak %s: trying to connect to entity: (%d %d)\n",
  1700. X        WHOAMI, pDest->lHost, pDest->iPort);
  1701. X
  1702. X
  1703. X    /** special case communications - shared memory **/
  1704. X
  1705. X    bSharedMem = ShMem_CanShareMem(pDest);
  1706. X
  1707. X    if (bSharedMem) {
  1708. X    iErr = ShMem_FindChannel(pDest->iPort, &pChannel);
  1709. X    }
  1710. X    else {
  1711. X    iErr = Sock_Connect(&iSocketFD,
  1712. X                pDest,
  1713. X                TALK_DEFAULT_PROTOCOL);
  1714. X    }
  1715. X    
  1716. X
  1717. X    if (iErr != VEOS_SUCCESS)  {
  1718. X
  1719. X    if (TALK_BUGS)
  1720. X        fprintf(stderr, "speak %s: cannot connect, talk: %d, sys: %d\n",
  1721. X            WHOAMI, iErr, errno);
  1722. X
  1723. X    iErr = VEOS_FAILURE;
  1724. X    }
  1725. X    
  1726. X    else {
  1727. X
  1728. X    if (TALK_BUGS) 
  1729. X        fprintf(stderr, "speak %s: connected to entity: (%d %d) on socket: %d\n",
  1730. X            WHOAMI, pDest->lHost, pDest->iPort, iSocketFD);
  1731. X    
  1732. X    
  1733. X    /** allocate a new connection record **/
  1734. X    
  1735. X    iErr = Shell_NewBlock(sizeof(TSpeakNode), &pNewNode, "speak node");
  1736. X    if (iErr != VEOS_SUCCESS) {
  1737. X        
  1738. X        if (!bSharedMem)
  1739. X        Sock_Close(&iSocketFD);
  1740. X        }
  1741. X
  1742. X    else {
  1743. X        /** setup connection record **/
  1744. X        
  1745. X        bcopy(pDest, &pNewNode->destRec, sizeof(TUid));
  1746. X        
  1747. X        if (bSharedMem) {
  1748. X        pNewNode->iConnType = TALK_SHMEM_CONN;
  1749. X        }
  1750. X        else {
  1751. X        pNewNode->iSocketFD = iSocketFD;
  1752. X        pNewNode->iConnType = TALK_SOCK_CONN;
  1753. X        }
  1754. X
  1755. X        pNewNode->pMessageQ = nil;
  1756. X        
  1757. X        
  1758. X        
  1759. X        /** return the address of record **/
  1760. X        
  1761. X        *hSpeakNode = pNewNode;
  1762. X        }
  1763. X    }
  1764. X    
  1765. X    return(iErr);
  1766. X    
  1767. X    } /* Talk_NewSpeakConnection */
  1768. X/****************************************************************************************/
  1769. X
  1770. X
  1771. X
  1772. X
  1773. X/****************************************************************************************/
  1774. XTVeosErr Talk_KillSpeakConnection(pDeadNode)
  1775. X    TPSpeakNode        pDeadNode;
  1776. X{
  1777. X    TVeosErr        iErr;
  1778. X    TPMessageNode    pMessageFinger, pTempLink;
  1779. X
  1780. X    iErr = VEOS_FAILURE;
  1781. X    
  1782. X    if (pDeadNode) {            /* sane? */
  1783. X    
  1784. X    if (pDeadNode->iConnType == TALK_SOCK_CONN) {
  1785. X
  1786. X        if (TALK_BUGS)
  1787. X        fprintf(stderr, "speak %s: closing connection on socket: %d\n",
  1788. X            WHOAMI, pDeadNode->iSocketFD);
  1789. X
  1790. X        
  1791. X        /** close the speak connection **/
  1792. X        
  1793. X        iErr = Sock_Close(&pDeadNode->iSocketFD);
  1794. X        }
  1795. X
  1796. X
  1797. X    if (TALK_BUGS)
  1798. X        fprintf(stderr, "speak %s: closed speak connection, talk: %d, sys: %d\n",
  1799. X            WHOAMI, iErr, errno);
  1800. X    
  1801. X    
  1802. X    /** deallocate queued messages nodes **/
  1803. X    
  1804. X    pMessageFinger = pDeadNode->pMessageQ;
  1805. X    while (pMessageFinger) {
  1806. X        
  1807. X        DUMP(pMessageFinger->sMessage);
  1808. X        
  1809. X        pTempLink = pMessageFinger->pLink;
  1810. X        Shell_ReturnBlock(pMessageFinger, sizeof(TMessageNode), "message node");
  1811. X        
  1812. X        pMessageFinger = pTempLink;
  1813. X        }
  1814. X    
  1815. X    
  1816. X    /** free allocated node **/
  1817. X    
  1818. X    Shell_ReturnBlock(pDeadNode, sizeof(TSpeakNode), "speak node");
  1819. X    
  1820. X    
  1821. X    iErr = VEOS_SUCCESS;
  1822. X    }
  1823. X    
  1824. X    return(iErr);
  1825. X    
  1826. X    } /* Talk_killSpeakConnection */
  1827. X/****************************************************************************************/
  1828. X
  1829. X
  1830. X
  1831. X
  1832. X/****************************************************************************************
  1833. X * Talk_RetrieveMessages                                */
  1834. X
  1835. XTVeosErr Talk_RetrieveMessages(iSocketFD)
  1836. X    int            iSocketFD;
  1837. X{
  1838. X    TVeosErr        iErr;
  1839. X    int            iBufferSize, iMsgLen, iBytesRead;
  1840. X    TMsgRec        pbMsg;
  1841. X    char        *pFinger;
  1842. X
  1843. X    /** grab each waiting message in buffer **/
  1844. X    
  1845. X    do {
  1846. X
  1847. X    /** read size of next message from FD **/
  1848. X    
  1849. X    iBufferSize = sizeof(int);
  1850. X    
  1851. X    iErr = Sock_Receive(iSocketFD, &iMsgLen, &iBufferSize);
  1852. X    if (iErr == VEOS_SUCCESS) {
  1853. X        
  1854. X        iMsgLen = ntohl(iMsgLen);
  1855. X#ifndef OPTIMAL
  1856. X        if (TALK_BUGS)
  1857. X        fprintf(stderr, "listen %s: incoming message size: %d\n",
  1858. X            WHOAMI, iMsgLen);
  1859. X#endif
  1860. X        /** read actual grouple message **/
  1861. X        
  1862. X        iBytesRead = 0, pFinger = TALK_BUFFER;
  1863. X        while (iErr == VEOS_SUCCESS) {
  1864. X
  1865. X        iBufferSize = iMsgLen - iBytesRead;
  1866. X        iErr = Sock_Receive(iSocketFD, pFinger, &iBufferSize);
  1867. X#ifndef OPTIMAL
  1868. X        if (TALK_BUGS) {
  1869. X            fprintf(stderr, "listen %s: receive returned %d bytes, talk: %d, sys: %d\n",
  1870. X                WHOAMI, iBufferSize, iErr, errno);
  1871. X            }
  1872. X#endif
  1873. X        if (iErr == VEOS_SUCCESS) {
  1874. X
  1875. X            iBytesRead += iBufferSize;
  1876. X            pFinger += iBufferSize;
  1877. X
  1878. X            if (iBytesRead == iMsgLen) {
  1879. X            pbMsg.iLen = iBytesRead;
  1880. X            pbMsg.sMessage = TALK_BUFFER;
  1881. X            
  1882. X            (*TALK_MSG_FUNC) (&pbMsg);
  1883. X            break;
  1884. X            }
  1885. X            }
  1886. X
  1887. X        /** spin and wait for remaining data.
  1888. X         ** there is a minimal possibility of deadlock
  1889. X         ** introduced here.
  1890. X         ** situations that may cause spinning to deadlock:
  1891. X         ** 1. sending an oversized message to yourself.
  1892. X         ** 2. sending an oversized message to a process
  1893. X         **    that is simultaneously sending an oversized
  1894. X         **    message to you.
  1895. X         ** Assumption: oversized messages are infrequent.
  1896. X         **/
  1897. X        else if (iBytesRead > 0 && iErr == TALK_LISTEN_BLOCKED) {
  1898. X#ifndef OPTIMAL
  1899. X            if (TALK_BUGS)
  1900. X            fprintf(stderr, "listen %s: spinning on partial message..\n", WHOAMI);
  1901. X#endif
  1902. X            iErr = VEOS_SUCCESS;
  1903. X            }
  1904. X        }
  1905. X        }
  1906. X
  1907. X    } while (iErr == VEOS_SUCCESS);
  1908. X    
  1909. X    return(iErr);
  1910. X    
  1911. X    } /* Talk_RetrieveMessages */
  1912. X/****************************************************************************************/
  1913. X
  1914. X
  1915. X
  1916. X/****************************************************************************************
  1917. X * Talk_ThrowMessages                                    */
  1918. X
  1919. XTVeosErr Talk_ThrowMessages(pSpeakNode, pDirty)
  1920. X    TPSpeakNode        pSpeakNode;
  1921. X    boolean        *pDirty;
  1922. X{
  1923. X    TVeosErr        iErr = VEOS_FAILURE;
  1924. X    
  1925. X    *pDirty = FALSE;
  1926. X
  1927. X    if (pSpeakNode->pMessageQ) {        /* any messages? */
  1928. X    
  1929. X    if (pSpeakNode->iConnType == TALK_SOCK_CONN)
  1930. X        iErr = Talk_SendMsgsOverNet(pSpeakNode);
  1931. X
  1932. X    else if (pSpeakNode->iConnType == TALK_SHMEM_CONN)
  1933. X        iErr = ShMem_WriteMessages(pSpeakNode);
  1934. X
  1935. X
  1936. X    /** mark this connection for pending messages **/
  1937. X
  1938. X    if (pSpeakNode->pMessageQ)
  1939. X        *pDirty = TRUE;
  1940. X    }
  1941. X    
  1942. X    return(iErr);
  1943. X    
  1944. X    } /* Talk_ThrowMessages */
  1945. X/****************************************************************************************/
  1946. X
  1947. X
  1948. X
  1949. X/****************************************************************************************/
  1950. XTVeosErr Talk_SendMsgsOverNet(pSpeakNode)
  1951. X    TPSpeakNode        pSpeakNode;
  1952. X{
  1953. X    int            iLen, iMsgLen, iBytesWritten;
  1954. X    TPMessageNode    pSaveLink;
  1955. X    char        *pFinger;
  1956. X    int            iSocketFD;
  1957. X    TVeosErr        iErr = VEOS_SUCCESS;
  1958. X    
  1959. X    iSocketFD = pSpeakNode->iSocketFD;
  1960. X    
  1961. X    /** dispatch message sending...
  1962. X     ** oldest jobs first to enforce sequencing
  1963. X     **/        
  1964. X    
  1965. X    do {
  1966. X    /** attempt to transmit oldest message **/
  1967. X    
  1968. X    pFinger = pSpeakNode->pMessageQ->sMessage;
  1969. X    iMsgLen = pSpeakNode->pMessageQ->iMsgLen;
  1970. X    iBytesWritten = 0;
  1971. X
  1972. X    while (iErr == VEOS_SUCCESS) {
  1973. X
  1974. X         
  1975. X        /** transmit the message **/
  1976. X
  1977. X        iLen = iMsgLen - iBytesWritten;
  1978. X        iErr = Sock_Transmit(iSocketFD, pFinger, &iLen);
  1979. X#ifndef OPTIMAL        
  1980. X        if (TALK_BUGS) {
  1981. X            fprintf(stderr, "speak %s: transmit sent %d bytes, talk: %d, sys: %d\n",
  1982. X                WHOAMI, iLen, iErr, errno);
  1983. X            }
  1984. X#endif        
  1985. X
  1986. X        if (iErr == VEOS_SUCCESS) {
  1987. X
  1988. X        iBytesWritten += iLen;
  1989. X        pFinger += iLen;
  1990. X
  1991. X        if (iBytesWritten == iMsgLen) {
  1992. X
  1993. X            /** dequeue this message from connection record **/
  1994. X            
  1995. X            DUMP(pSpeakNode->pMessageQ->sMessage);
  1996. X            
  1997. X            pSaveLink = pSpeakNode->pMessageQ->pLink;
  1998. X            Shell_ReturnBlock(pSpeakNode->pMessageQ,
  1999. X                      sizeof(TMessageNode), "message node");
  2000. X            pSpeakNode->pMessageQ = pSaveLink;
  2001. X
  2002. X            break;
  2003. X            }
  2004. X        }
  2005. X
  2006. X        /** spin and wait for line to free.
  2007. X         ** there is a minimal possibility of deadlock
  2008. X         ** introduced here.
  2009. X         ** situations that may cause spinning to deadlock:
  2010. X         ** 1. sending an oversized message to yourself.
  2011. X         ** 2. sending an oversized message to a process
  2012. X         **    that is simultaneously sending an oversized
  2013. X         **    message to you.
  2014. X         ** Assumption: oversized messages are infrequent.
  2015. X         **/
  2016. X        else if (iBytesWritten > 0 && iErr == TALK_SPEAK_BLOCKED) {
  2017. X#ifndef OPTIMAL
  2018. X        if (TALK_BUGS)
  2019. X            fprintf(stderr, "speak %s: spinning on partial message..\n", WHOAMI);
  2020. X#endif
  2021. X        iErr = VEOS_SUCCESS;
  2022. X        }
  2023. X
  2024. X        } /* while more to write */
  2025. X    
  2026. X
  2027. X    } while (pSpeakNode->pMessageQ);
  2028. X
  2029. X    return(iErr);
  2030. X
  2031. X    } /* Talk_SendMsgsOverNet */
  2032. X/****************************************************************************************/
  2033. X
  2034. X
  2035. X
  2036. X/****************************************************************************************
  2037. X * Talk_AddSpeakJob                                    */
  2038. X
  2039. XTVeosErr Talk_AddSpeakJob(pDestNode, pMsgBlock)
  2040. X    TPSpeakNode        pDestNode;
  2041. X    TPMsgRec        pMsgBlock;
  2042. X{
  2043. X    TVeosErr        iErr;
  2044. X    TPMessageNode    pNewJob;
  2045. X    THMessageNode    hFinger;
  2046. X    
  2047. X    /** allocate new outgoing message job record **/
  2048. X    
  2049. X    iErr = Shell_NewBlock(sizeof(TMessageNode), &pNewJob, "message node");
  2050. X    if (iErr == VEOS_SUCCESS) {
  2051. X    
  2052. X
  2053. X    /** setup job record **/
  2054. X
  2055. X    if (NEWPTR(pNewJob->sMessage, char *, pMsgBlock->iLen + 4)) {
  2056. X        
  2057. X        /** insert length code at front of message **/
  2058. X        *(long *) pNewJob->sMessage = htonl(pMsgBlock->iLen);
  2059. X        
  2060. X        bcopy(pMsgBlock->sMessage, pNewJob->sMessage + 4, pMsgBlock->iLen);
  2061. X        pNewJob->iMsgLen = pMsgBlock->iLen + 4;
  2062. X        pNewJob->pLink = nil;
  2063. X    
  2064. X        /** append new job to destination's message queue **/
  2065. X        
  2066. X        hFinger = &pDestNode->pMessageQ;
  2067. X        while (*hFinger)
  2068. X        hFinger = &(*hFinger)->pLink;
  2069. X        
  2070. X        *hFinger = pNewJob;
  2071. X        
  2072. X        iErr = VEOS_SUCCESS;
  2073. X        }
  2074. X    }
  2075. X
  2076. X    
  2077. X    if (iErr != VEOS_SUCCESS) {
  2078. X    
  2079. X    /** cleanup any mess **/
  2080. X    
  2081. X    if (pNewJob) {
  2082. X        if (pNewJob->sMessage)
  2083. X        DUMP(pNewJob->sMessage);
  2084. X        Shell_ReturnBlock(pNewJob, sizeof(TMessageNode), "message node");
  2085. X        }
  2086. X    }
  2087. X    
  2088. X    return(iErr);
  2089. X    
  2090. X    } /* Talk_AddSpeakJob */
  2091. X/****************************************************************************************/
  2092. X
  2093. X
  2094. X
  2095. X/****************************************************************************************/
  2096. XTVeosErr Talk_DummyMsgHandler(pMsgRec)
  2097. X    TPMsgRec        pMsgRec;
  2098. X{
  2099. X    char        *pBuf;
  2100. X    
  2101. X    if (TALK_BUGS) {
  2102. X    fprintf(stderr, "listen %s: message not converted.\n", WHOAMI);
  2103. X    }    
  2104. X
  2105. X    return(VEOS_SUCCESS);
  2106. X
  2107. X    } /* Talk_DummyMsgHandler */
  2108. X/****************************************************************************************/
  2109. X
  2110. X
  2111. X#ifdef banana
  2112. Xint Talk_ConnectTrap();
  2113. X
  2114. X/****************************************************************************************/
  2115. Xint Talk_ConnectTrap(iSignal, iCode, context, pAddr)
  2116. X    int            iSignal, iCode;
  2117. X    struct sigcontext    *context;
  2118. X    char        *pAddr;
  2119. X{
  2120. X    if (iSignal == SIGIO)
  2121. X    NEW_CONN = TRUE;
  2122. X
  2123. X    return(0);
  2124. X    }
  2125. X/****************************************************************************************/
  2126. X#endif
  2127. X
  2128. X
  2129. X
  2130. X
  2131. X
  2132. X
  2133. X
  2134. X
  2135. END_OF_FILE
  2136. if test 24919 -ne `wc -c <'kernel_private/src/talk/talk.c'`; then
  2137.     echo shar: \"'kernel_private/src/talk/talk.c'\" unpacked with wrong size!
  2138. fi
  2139. # end of 'kernel_private/src/talk/talk.c'
  2140. fi
  2141. if test -f 'src/kernel_current/talk/talk.c' -a "${1}" != "-c" ; then 
  2142.   echo shar: Will not clobber existing file \"'src/kernel_current/talk/talk.c'\"
  2143. else
  2144. echo shar: Extracting \"'src/kernel_current/talk/talk.c'\" \(24919 characters\)
  2145. sed "s/^X//" >'src/kernel_current/talk/talk.c' <<'END_OF_FILE'
  2146. X/****************************************************************************************
  2147. X *                                            *
  2148. X * file: talk.c                                        *
  2149. X *                                            *
  2150. X * October 20, 1990: an entity's network interface to other entities.                   *
  2151. X *                                            *
  2152. X *             this library represents the presentation & session layers of the    *
  2153. X *             ISO network systems model.                        *
  2154. X *                                            *
  2155. X *                   the network and transport layers provided by socket.c        *
  2156. X *                                            *
  2157. X * by Geoffrey P. Coco at the HITLab, Seattle.                          *
  2158. X *                                            *
  2159. X ****************************************************************************************/
  2160. X
  2161. X
  2162. X/****************************************************************************************
  2163. X * Copyright (C) 1992  Geoffrey P. Coco, Human Interface Technology Lab, Seattle    *
  2164. X ****************************************************************************************/
  2165. X
  2166. X
  2167. X/****************************************************************************************
  2168. X                      Preliminaries
  2169. X ****************************************************************************************/
  2170. X
  2171. X#include "kernel.h"
  2172. X#include "errno.h"
  2173. X#include "sys/signal.h"
  2174. X
  2175. X/****************************************************************************************/
  2176. X
  2177. XTVeosErr Talk_DummyMsgHandler();
  2178. X
  2179. X/****************************************************************************************/
  2180. X
  2181. X
  2182. X
  2183. X/****************************************************************************************
  2184. X * Talk_HelloTalk                                    *
  2185. X *                                            *
  2186. X * talk initialization.  call Talk_HelloTalk() once, and don't proceed upon failure.    */
  2187. X
  2188. XTVeosErr Talk_HelloTalk(iPort, pMessFun)
  2189. X    int            iPort;
  2190. X    TVeosErr        (*pMessFun) ();
  2191. X{
  2192. X    TVeosErr        iErr;
  2193. X    
  2194. X
  2195. X    /** allocate fast message buffers **/
  2196. X    
  2197. X    iErr = VEOS_MEM_ERR;
  2198. X    if (NEWPTR(TALK_BUFFER, char *, TALK_MAX_BUFFER)) {
  2199. X    
  2200. X
  2201. X    /** initialize cache settings **/
  2202. X    
  2203. X    SPEAK_SET = nil;
  2204. X    
  2205. X    LISTEN_SOCKETFD = TALK_BOGUS_FD;
  2206. X    LISTEN_SET = nil;
  2207. X    
  2208. X    FD_ZERO(&OPEN_READ_SOCKETS);
  2209. X    FD_ZERO(&OPEN_WRITE_SOCKETS);
  2210. X    
  2211. X    TALK_MSG_FUNC = pMessFun ? pMessFun : Talk_DummyMsgHandler;
  2212. X    
  2213. X    bzero(SOCK_HOSTS, 26 * sizeof(TPHostNode));
  2214. X    
  2215. X    
  2216. X    /** initialize public cache settings **/
  2217. X    
  2218. X    SPEAK_DIRTY = FALSE;
  2219. X    
  2220. X    
  2221. X    
  2222. X    /** initialize listen connection **/
  2223. X    
  2224. X    iErr = Talk_OpenPort(iPort);
  2225. X    }
  2226. X    
  2227. X    return(iErr);
  2228. X    
  2229. X    } /* Talk_HelloTalk */
  2230. X/****************************************************************************************/
  2231. X
  2232. X
  2233. X
  2234. X
  2235. X/****************************************************************************************
  2236. X * Talk_ByeTalk                                        *
  2237. X *                                             *
  2238. X * cleanup network and memory allocation only after finished using talk library.    */
  2239. X
  2240. XTVeosErr Talk_ByeTalk()
  2241. X{
  2242. X    TPSpeakNode            pSpeakFinger, pTempSpeak;
  2243. X    TPListenNode        pListenFinger, pTempListen;
  2244. X
  2245. X    /** take down listen port **/
  2246. X    
  2247. X    Talk_ClosePort();
  2248. X    
  2249. X    
  2250. X    /** close all speak connections **/
  2251. X    
  2252. X    pSpeakFinger = SPEAK_SET;
  2253. X    while (pSpeakFinger) {
  2254. X    
  2255. X    pTempSpeak = pSpeakFinger->pLink;
  2256. X    
  2257. X    Talk_KillSpeakConnection(pSpeakFinger);
  2258. X    
  2259. X    pSpeakFinger = pTempSpeak;
  2260. X    }
  2261. X    
  2262. X    
  2263. X    /** close listen connections (normal mechanism is while attempting to read) **/
  2264. X    
  2265. X    pListenFinger = LISTEN_SET;
  2266. X    while (pListenFinger) {
  2267. X    
  2268. X    pTempListen = pListenFinger->pLink;
  2269. X    
  2270. X    Talk_KillListenConnection(pListenFinger);
  2271. X    
  2272. X    pListenFinger = pTempListen;
  2273. X    }
  2274. X
  2275. X    
  2276. X    /** deallocate local library cache **/
  2277. X    
  2278. X    if (TALK_BUFFER)
  2279. X    DUMP(TALK_BUFFER);
  2280. X    
  2281. X    
  2282. X    return(VEOS_SUCCESS);
  2283. X    
  2284. X    } /* Talk_ByeTalk */
  2285. X/****************************************************************************************/
  2286. X
  2287. X
  2288. X
  2289. X/****************************************************************************************/
  2290. XTVeosErr Talk_SpeakToMany(pDests, pMsg)
  2291. X    TPUidNode        pDests;
  2292. X    TPMsgRec        pMsg;
  2293. X{
  2294. X    TVeosErr        iErr;
  2295. X    TPUidNode        pFinger;
  2296. X
  2297. X    iErr = VEOS_FAILURE;
  2298. X
  2299. X    if (pDests && pMsg) {
  2300. X
  2301. X    iErr = VEOS_SUCCESS;
  2302. X
  2303. X    pFinger = pDests;
  2304. X    while (pFinger && iErr == VEOS_SUCCESS) {
  2305. X
  2306. X        iErr = Talk_PostSpeakMessage(&pFinger->addr, pMsg);
  2307. X
  2308. X        pFinger = pFinger->pNext;
  2309. X        }
  2310. X    }
  2311. X
  2312. X    return(iErr);
  2313. X
  2314. X    } /* Talk_SpeakToMany */
  2315. X/****************************************************************************************/
  2316. X
  2317. X
  2318. X
  2319. X/****************************************************************************************
  2320. X *                     private functions                    *
  2321. X ****************************************************************************************/
  2322. X
  2323. X
  2324. X/****************************************************************************************
  2325. X * Talk_OpenPort                                    *
  2326. X *                                            *
  2327. X * establish an incoming message gateway for the entity client.                *
  2328. X * Talk_OpenPort() should be paired with a call to Talk_ClosePort().            */
  2329. X
  2330. XTVeosErr Talk_OpenPort(iPort)
  2331. X    int            iPort;
  2332. X{
  2333. X    TVeosErr        iErr;
  2334. X    boolean        bFound;
  2335. X
  2336. X    
  2337. X    /** install entity connection handler **/
  2338. X/*
  2339. X    signal(SIGIO, Talk_ConnectTrap);
  2340. X*/
  2341. X    
  2342. X    
  2343. X    /** initiate network comminication. alert world of our existence. **/
  2344. X
  2345. X    if (TALK_BUGS)
  2346. X    fprintf(stderr, "listen %s: trying to listen...\n", WHOAMI);
  2347. X
  2348. X
  2349. X    if (iPort != TALK_BOGUS_PORT) {
  2350. X    
  2351. X    /** use chosen port number **/
  2352. X    
  2353. X    iErr = Sock_Listen(&LISTEN_SOCKETFD,
  2354. X                     iPort,
  2355. X                     "tcp",
  2356. X                     TALK_AGRESSIVE);
  2357. X    }
  2358. X    else {
  2359. X    /** try all sockets until we find an unused one **/
  2360. X    
  2361. X    iPort = TALK_MIN_PORT;
  2362. X    iErr = VEOS_FAILURE;
  2363. X    
  2364. X    while (iErr != VEOS_SUCCESS &&
  2365. X           iPort < TALK_MAX_PORT) {
  2366. X        
  2367. X        iErr = Sock_Listen(&LISTEN_SOCKETFD,
  2368. X                     iPort,
  2369. X                     "tcp",
  2370. X                     TALK_PASSIVE);
  2371. X        if (iErr != VEOS_SUCCESS)
  2372. X        iPort ++;
  2373. X        }
  2374. X    }
  2375. X    
  2376. X    
  2377. X    if (iErr != VEOS_SUCCESS) {
  2378. X    if (TALK_BUGS)
  2379. X        fprintf(stderr, "listen %s: cannot listen, talk: %d, sys: %d\n",
  2380. X            WHOAMI,  iErr, errno);
  2381. X    }
  2382. X
  2383. X    else {
  2384. X    /** maintain references to entity uid **/
  2385. X    
  2386. X    IDENT_ADDR.iPort = iPort;
  2387. X    Shell_UpdateUid();
  2388. X
  2389. X    if (TALK_BUGS)
  2390. X        fprintf(stderr, "listen %s: successful listen\n", WHOAMI);
  2391. X
  2392. X
  2393. X    /** setup shared memory channel **/
  2394. X
  2395. X    iErr = ShMem_Init();
  2396. X    }
  2397. X
  2398. X    return(iErr);
  2399. X    
  2400. X    } /* Talk_OpenPort */
  2401. X/****************************************************************************************/
  2402. X
  2403. X
  2404. X
  2405. X/****************************************************************************************
  2406. X * Talk_ClosePort                                    *
  2407. X *                                                   *
  2408. X * close the incoming message gateway.  the cleanup counterpart to Talk_OpenTalk().    */
  2409. X
  2410. XTVeosErr Talk_ClosePort()
  2411. X{
  2412. X    TVeosErr        iErr;
  2413. X    
  2414. X
  2415. X    /** unregister ourselves from net **/
  2416. X    
  2417. X    if (TALK_BUGS)
  2418. X    fprintf(stderr, "listen %s: about to close main listen socket: %d, sys: %d\n",
  2419. X        WHOAMI, LISTEN_SOCKETFD, errno);
  2420. X    
  2421. X
  2422. X    iErr = Sock_Close(&LISTEN_SOCKETFD);
  2423. X    
  2424. X    if (TALK_BUGS)
  2425. X    fprintf(stderr, "listen %s: closed main listen port, talk: %d, sys: %d\n",
  2426. X        WHOAMI, iErr, errno);
  2427. X
  2428. X
  2429. X    /** takedown shared memory channel **/
  2430. X    
  2431. X    ShMem_Close();
  2432. X
  2433. X
  2434. X    return(iErr);
  2435. X    
  2436. X    } /* Talk_ClosePort */
  2437. X/****************************************************************************************/
  2438. X
  2439. X
  2440. X
  2441. X
  2442. X/****************************************************************************************/
  2443. XTVeosErr Talk_GatherListenMessages()
  2444. X{
  2445. X    TVeosErr           iErr;
  2446. X    int            iSocketFD;
  2447. X    THListenNode    hListenFinger;
  2448. X    TPListenNode        pSaveLink;
  2449. X    
  2450. X    
  2451. X    hListenFinger = &LISTEN_SET;
  2452. X    
  2453. X    while (*hListenFinger) {
  2454. X
  2455. X    pSaveLink = *hListenFinger;
  2456. X    iSocketFD = (*hListenFinger)->iSocketFD;
  2457. X    
  2458. X
  2459. X    /** attempt to read messages from the connection **/
  2460. X    
  2461. X    iErr = Talk_RetrieveMessages(iSocketFD);
  2462. X    if (iErr != TALK_CONN_CLOSED)
  2463. X        
  2464. X        hListenFinger = &(*hListenFinger)->pLink;        
  2465. X    
  2466. X    
  2467. X    else {
  2468. X        /** connection was lost from other end **/
  2469. X
  2470. X        if (TALK_BUGS)
  2471. X        fprintf(stderr, "listen %s: lost connection on socket: %d\n",
  2472. X            WHOAMI, iSocketFD);
  2473. X
  2474. X        pSaveLink = (*hListenFinger)->pLink;
  2475. X        
  2476. X        Talk_KillListenConnection(*hListenFinger);
  2477. X        
  2478. X        *hListenFinger = pSaveLink;
  2479. X        }
  2480. X    }
  2481. X
  2482. X
  2483. X    /** all shared memory messages come in through one channel **/
  2484. X    
  2485. X    ShMem_GatherMessages();
  2486. X
  2487. X
  2488. X    return(iErr);
  2489. X    
  2490. X    } /* Talk_GatherListenMessages */
  2491. X/****************************************************************************************/
  2492. X
  2493. X
  2494. X
  2495. X
  2496. X/****************************************************************************************
  2497. X * Talk_EstNewListenConnections                                */
  2498. X
  2499. XTVeosErr Talk_EstNewListenConnections()
  2500. X{
  2501. X    TVeosErr        iErr = VEOS_SUCCESS;
  2502. X    TPListenNode    pNewNode;
  2503. X    
  2504. X    iErr = Talk_NewListenConnection(LISTEN_SOCKETFD, &pNewNode);
  2505. X    if (iErr == VEOS_SUCCESS) {
  2506. X    
  2507. X    /** store this record locally **/
  2508. X    
  2509. X    pNewNode->pLink = LISTEN_SET;
  2510. X    LISTEN_SET = pNewNode;
  2511. X    }
  2512. X
  2513. X    return(VEOS_SUCCESS);
  2514. X    
  2515. X    } /* Talk_EstNewListenConnections */
  2516. X/****************************************************************************************/
  2517. X
  2518. X
  2519. X
  2520. X/****************************************************************************************/
  2521. XTVeosErr Talk_DispatchQedSpeakMessages()
  2522. X{
  2523. X    TVeosErr        iErr;
  2524. X    THSpeakNode        hSpeakFinger;
  2525. X    TPSpeakNode        pSaveLink;
  2526. X    boolean        bLocalDirty;
  2527. X    
  2528. X    iErr = VEOS_SUCCESS;
  2529. X    
  2530. X
  2531. X    /** inspect every open connection for queued outgoing messages **/
  2532. X    
  2533. X    hSpeakFinger = &SPEAK_SET;
  2534. X    SPEAK_DIRTY = FALSE;
  2535. X    
  2536. X    while (*hSpeakFinger) {
  2537. X    
  2538. X    
  2539. X    /** attempt to send queued messages for this connection in order **/
  2540. X    
  2541. X    iErr = Talk_ThrowMessages(*hSpeakFinger, &bLocalDirty);
  2542. X    if (iErr == TALK_CONN_CLOSED) {
  2543. X        
  2544. X        
  2545. X        /** connection was lost from other end **/
  2546. X
  2547. X        if (TALK_BUGS)
  2548. X        fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
  2549. X            WHOAMI,
  2550. X            (*hSpeakFinger)->destRec.lHost,
  2551. X            (*hSpeakFinger)->destRec.iPort,
  2552. X            (*hSpeakFinger)->iSocketFD);
  2553. X        
  2554. X        pSaveLink = (*hSpeakFinger)->pLink;
  2555. X        
  2556. X        Talk_KillSpeakConnection(*hSpeakFinger);
  2557. X        
  2558. X        *hSpeakFinger = pSaveLink;
  2559. X        }
  2560. X    
  2561. X    else {
  2562. X        if (bLocalDirty)
  2563. X        SPEAK_DIRTY = TRUE;
  2564. X        
  2565. X        
  2566. X        /** check next connection **/
  2567. X        
  2568. X        hSpeakFinger = &(*hSpeakFinger)->pLink;        
  2569. X        }
  2570. X    }
  2571. X
  2572. X    return(iErr);
  2573. X    
  2574. X    } /* Talk_DispatchQedSpeakMessages */
  2575. X/****************************************************************************************/
  2576. X
  2577. X
  2578. X
  2579. X
  2580. X/****************************************************************************************
  2581. X * Talk_NewListenConnection                                */
  2582. X
  2583. XTVeosErr Talk_NewListenConnection(iListenSocketFD, hListenNode)
  2584. X    int            iListenSocketFD;
  2585. X    THListenNode    hListenNode;
  2586. X{
  2587. X    TPListenNode    pNewNode;
  2588. X    TVeosErr        iErr;
  2589. X    int            iSocketFD;
  2590. X    
  2591. X    
  2592. X    iErr = Sock_ReadSelect(iListenSocketFD);
  2593. X    if (iErr == VEOS_SUCCESS) {    
  2594. X
  2595. X    if (TALK_BUGS)
  2596. X        fprintf(stderr, "listen %s: another entity is trying to connect...\n",
  2597. X            WHOAMI);
  2598. X    
  2599. X    /** establish a full-duplex connection **/
  2600. X    
  2601. X    iErr = Sock_Accept(iListenSocketFD, &iSocketFD);
  2602. X    
  2603. X    if (iErr != VEOS_SUCCESS)
  2604. X        perror("talk: _Accept");
  2605. X    
  2606. X    else {
  2607. X
  2608. X        if (TALK_BUGS)
  2609. X        fprintf(stderr, "listen %s: another entity connected on socket: %d\n",
  2610. X            WHOAMI, iSocketFD);
  2611. X
  2612. X        /** allocate listen connection record **/
  2613. X        
  2614. X        iErr = Shell_NewBlock(sizeof(TListenNode), &pNewNode, "listen node");
  2615. X        if (iErr != VEOS_SUCCESS) {
  2616. X
  2617. X        Sock_Close(&iSocketFD);
  2618. X        }
  2619. X        
  2620. X        else {
  2621. X        /** setup connection record **/
  2622. X        
  2623. X        pNewNode->iSocketFD = iSocketFD;
  2624. X        pNewNode->pLink = nil;
  2625. X        
  2626. X        *hListenNode = pNewNode;
  2627. X        }
  2628. X        }
  2629. X    }
  2630. X    
  2631. X    return(iErr);
  2632. X    
  2633. X    } /* Talk_NewListenConnection */
  2634. X/****************************************************************************************/
  2635. X
  2636. X
  2637. X
  2638. X
  2639. X/****************************************************************************************/
  2640. XTVeosErr Talk_KillListenConnection(pDeadNode)
  2641. X    TPListenNode    pDeadNode;
  2642. X{
  2643. X    TVeosErr        iErr;
  2644. X    
  2645. X    iErr = VEOS_FAILURE;
  2646. X    
  2647. X    if (pDeadNode) {            /* sane? */
  2648. X    
  2649. X    if (TALK_BUGS) 
  2650. X        fprintf(stderr, "listen %s: closing connection on socket: %d\n",
  2651. X            WHOAMI, pDeadNode->iSocketFD);
  2652. X    
  2653. X    /** strike this connection in all respects **/
  2654. X    
  2655. X        iErr = Sock_Close(&pDeadNode->iSocketFD);
  2656. X
  2657. X
  2658. X    if (TALK_BUGS)
  2659. X        fprintf(stderr, "listen %s: closed listen connection, talk: %d, sys: %d\n",
  2660. X            WHOAMI, iErr, errno);
  2661. X
  2662. X
  2663. X    Shell_ReturnBlock(pDeadNode, sizeof(TListenNode), "listen node");
  2664. X    
  2665. X    iErr = VEOS_SUCCESS;
  2666. X    }
  2667. X    
  2668. X    return(iErr);
  2669. X    
  2670. X    } /* Talk_KillListenConnection */
  2671. X/****************************************************************************************/
  2672. X
  2673. X
  2674. X
  2675. X/****************************************************************************************/
  2676. XTVeosErr Talk_PostSpeakMessage(pDest, pMsgBlock)
  2677. X    TPUid        pDest;
  2678. X    TPMsgRec        pMsgBlock;
  2679. X{
  2680. X    TVeosErr        iErr;
  2681. X    TPSpeakNode        pDestNode, pSaveLink;
  2682. X    THSpeakNode        hFinger;
  2683. X    boolean        bLocalDirty;
  2684. X
  2685. X    if (pDest) {
  2686. X
  2687. X
  2688. X    /** do we already have a connection to this destination? **/
  2689. X    
  2690. X    hFinger = &SPEAK_SET;
  2691. X    iErr = VEOS_FAILURE;
  2692. X    
  2693. X    while (*hFinger && iErr != VEOS_SUCCESS) {
  2694. X        
  2695. X        if (UID_COMPARE(&(*hFinger)->destRec, pDest)) {
  2696. X        
  2697. X        pDestNode = *hFinger;
  2698. X        iErr = VEOS_SUCCESS;
  2699. X        }
  2700. X        else
  2701. X        hFinger = &(*hFinger)->pLink;        
  2702. X        }
  2703. X    
  2704. X    
  2705. X    /** attempt to connect to this destaination for the first time **/
  2706. X    
  2707. X    if (iErr != VEOS_SUCCESS) {
  2708. X        iErr = Talk_NewSpeakConnection(pDest,
  2709. X                           &pDestNode);
  2710. X        if (iErr == VEOS_SUCCESS) {
  2711. X        
  2712. X        /** add connection record to local list **/
  2713. X        
  2714. X        pDestNode->pLink = SPEAK_SET;
  2715. X        SPEAK_SET = pDestNode;
  2716. X        hFinger = &SPEAK_SET;
  2717. X        }
  2718. X        }
  2719. X    
  2720. X    
  2721. X    /** add new message to this connection's queue **/
  2722. X    
  2723. X    if (iErr == VEOS_SUCCESS) {
  2724. X        iErr = Talk_AddSpeakJob(pDestNode, pMsgBlock); 
  2725. X        if (iErr == VEOS_SUCCESS) {
  2726. X        
  2727. X        
  2728. X        /** attempt to send this message right now **/
  2729. X        
  2730. X        iErr = Talk_ThrowMessages(pDestNode, &bLocalDirty);
  2731. X        if (iErr == TALK_CONN_CLOSED) {
  2732. X            
  2733. X            
  2734. X            /** connection was lost from other end **/
  2735. X
  2736. X            if (TALK_BUGS)
  2737. X            fprintf(stderr, "speak %s: lost connection to (%d %d) on socket: %d\n",
  2738. X                WHOAMI,
  2739. X                pDestNode->destRec.lHost,
  2740. X                pDestNode->destRec.iPort,
  2741. X                pDestNode->iSocketFD);
  2742. X
  2743. X            
  2744. X            pSaveLink = pDestNode->pLink;
  2745. X            
  2746. X            Talk_KillSpeakConnection(pDestNode);
  2747. X            
  2748. X            *hFinger = pSaveLink;
  2749. X            }
  2750. X
  2751. X        else if (bLocalDirty)
  2752. X            SPEAK_DIRTY = TRUE;
  2753. X        }
  2754. X        }
  2755. X    }
  2756. X
  2757. X    return(iErr);
  2758. X    
  2759. X    } /* Talk_PostSpeakMessage */
  2760. X/****************************************************************************************/
  2761. X
  2762. X
  2763. X
  2764. X/****************************************************************************************
  2765. X * Talk_NewSpeakConnection                                */
  2766. X
  2767. XTVeosErr Talk_NewSpeakConnection(pDest, hSpeakNode)
  2768. X    TPUid        pDest;
  2769. X    THSpeakNode        hSpeakNode;
  2770. X{
  2771. X    TPSpeakNode        pNewNode;
  2772. X    int            iSocketFD;
  2773. X    TPSharedRec        pChannel;
  2774. X    TVeosErr        iErr;
  2775. X    boolean        bSharedMem;
  2776. X
  2777. X    *hSpeakNode = nil;
  2778. X    
  2779. X    
  2780. X    /** try to connect to destination shell **/
  2781. X
  2782. X    if (TALK_BUGS)    
  2783. X    fprintf(stderr, "speak %s: trying to connect to entity: (%d %d)\n",
  2784. X        WHOAMI, pDest->lHost, pDest->iPort);
  2785. X
  2786. X
  2787. X    /** special case communications - shared memory **/
  2788. X
  2789. X    bSharedMem = ShMem_CanShareMem(pDest);
  2790. X
  2791. X    if (bSharedMem) {
  2792. X    iErr = ShMem_FindChannel(pDest->iPort, &pChannel);
  2793. X    }
  2794. X    else {
  2795. X    iErr = Sock_Connect(&iSocketFD,
  2796. X                pDest,
  2797. X                TALK_DEFAULT_PROTOCOL);
  2798. X    }
  2799. X    
  2800. X
  2801. X    if (iErr != VEOS_SUCCESS)  {
  2802. X
  2803. X    if (TALK_BUGS)
  2804. X        fprintf(stderr, "speak %s: cannot connect, talk: %d, sys: %d\n",
  2805. X            WHOAMI, iErr, errno);
  2806. X
  2807. X    iErr = VEOS_FAILURE;
  2808. X    }
  2809. X    
  2810. X    else {
  2811. X
  2812. X    if (TALK_BUGS) 
  2813. X        fprintf(stderr, "speak %s: connected to entity: (%d %d) on socket: %d\n",
  2814. X            WHOAMI, pDest->lHost, pDest->iPort, iSocketFD);
  2815. X    
  2816. X    
  2817. X    /** allocate a new connection record **/
  2818. X    
  2819. X    iErr = Shell_NewBlock(sizeof(TSpeakNode), &pNewNode, "speak node");
  2820. X    if (iErr != VEOS_SUCCESS) {
  2821. X        
  2822. X        if (!bSharedMem)
  2823. X        Sock_Close(&iSocketFD);
  2824. X        }
  2825. X
  2826. X    else {
  2827. X        /** setup connection record **/
  2828. X        
  2829. X        bcopy(pDest, &pNewNode->destRec, sizeof(TUid));
  2830. X        
  2831. X        if (bSharedMem) {
  2832. X        pNewNode->iConnType = TALK_SHMEM_CONN;
  2833. X        }
  2834. X        else {
  2835. X        pNewNode->iSocketFD = iSocketFD;
  2836. X        pNewNode->iConnType = TALK_SOCK_CONN;
  2837. X        }
  2838. X
  2839. X        pNewNode->pMessageQ = nil;
  2840. X        
  2841. X        
  2842. X        
  2843. X        /** return the address of record **/
  2844. X        
  2845. X        *hSpeakNode = pNewNode;
  2846. X        }
  2847. X    }
  2848. X    
  2849. X    return(iErr);
  2850. X    
  2851. X    } /* Talk_NewSpeakConnection */
  2852. X/****************************************************************************************/
  2853. X
  2854. X
  2855. X
  2856. X
  2857. X/****************************************************************************************/
  2858. XTVeosErr Talk_KillSpeakConnection(pDeadNode)
  2859. X    TPSpeakNode        pDeadNode;
  2860. X{
  2861. X    TVeosErr        iErr;
  2862. X    TPMessageNode    pMessageFinger, pTempLink;
  2863. X
  2864. X    iErr = VEOS_FAILURE;
  2865. X    
  2866. X    if (pDeadNode) {            /* sane? */
  2867. X    
  2868. X    if (pDeadNode->iConnType == TALK_SOCK_CONN) {
  2869. X
  2870. X        if (TALK_BUGS)
  2871. X        fprintf(stderr, "speak %s: closing connection on socket: %d\n",
  2872. X            WHOAMI, pDeadNode->iSocketFD);
  2873. X
  2874. X        
  2875. X        /** close the speak connection **/
  2876. X        
  2877. X        iErr = Sock_Close(&pDeadNode->iSocketFD);
  2878. X        }
  2879. X
  2880. X
  2881. X    if (TALK_BUGS)
  2882. X        fprintf(stderr, "speak %s: closed speak connection, talk: %d, sys: %d\n",
  2883. X            WHOAMI, iErr, errno);
  2884. X    
  2885. X    
  2886. X    /** deallocate queued messages nodes **/
  2887. X    
  2888. X    pMessageFinger = pDeadNode->pMessageQ;
  2889. X    while (pMessageFinger) {
  2890. X        
  2891. X        DUMP(pMessageFinger->sMessage);
  2892. X        
  2893. X        pTempLink = pMessageFinger->pLink;
  2894. X        Shell_ReturnBlock(pMessageFinger, sizeof(TMessageNode), "message node");
  2895. X        
  2896. X        pMessageFinger = pTempLink;
  2897. X        }
  2898. X    
  2899. X    
  2900. X    /** free allocated node **/
  2901. X    
  2902. X    Shell_ReturnBlock(pDeadNode, sizeof(TSpeakNode), "speak node");
  2903. X    
  2904. X    
  2905. X    iErr = VEOS_SUCCESS;
  2906. X    }
  2907. X    
  2908. X    return(iErr);
  2909. X    
  2910. X    } /* Talk_killSpeakConnection */
  2911. X/****************************************************************************************/
  2912. X
  2913. X
  2914. X
  2915. X
  2916. X/****************************************************************************************
  2917. X * Talk_RetrieveMessages                                */
  2918. X
  2919. XTVeosErr Talk_RetrieveMessages(iSocketFD)
  2920. X    int            iSocketFD;
  2921. X{
  2922. X    TVeosErr        iErr;
  2923. X    int            iBufferSize, iMsgLen, iBytesRead;
  2924. X    TMsgRec        pbMsg;
  2925. X    char        *pFinger;
  2926. X
  2927. X    /** grab each waiting message in buffer **/
  2928. X    
  2929. X    do {
  2930. X
  2931. X    /** read size of next message from FD **/
  2932. X    
  2933. X    iBufferSize = sizeof(int);
  2934. X    
  2935. X    iErr = Sock_Receive(iSocketFD, &iMsgLen, &iBufferSize);
  2936. X    if (iErr == VEOS_SUCCESS) {
  2937. X        
  2938. X        iMsgLen = ntohl(iMsgLen);
  2939. X#ifndef OPTIMAL
  2940. X        if (TALK_BUGS)
  2941. X        fprintf(stderr, "listen %s: incoming message size: %d\n",
  2942. X            WHOAMI, iMsgLen);
  2943. X#endif
  2944. X        /** read actual grouple message **/
  2945. X        
  2946. X        iBytesRead = 0, pFinger = TALK_BUFFER;
  2947. X        while (iErr == VEOS_SUCCESS) {
  2948. X
  2949. X        iBufferSize = iMsgLen - iBytesRead;
  2950. X        iErr = Sock_Receive(iSocketFD, pFinger, &iBufferSize);
  2951. X#ifndef OPTIMAL
  2952. X        if (TALK_BUGS) {
  2953. X            fprintf(stderr, "listen %s: receive returned %d bytes, talk: %d, sys: %d\n",
  2954. X                WHOAMI, iBufferSize, iErr, errno);
  2955. X            }
  2956. X#endif
  2957. X        if (iErr == VEOS_SUCCESS) {
  2958. X
  2959. X            iBytesRead += iBufferSize;
  2960. X            pFinger += iBufferSize;
  2961. X
  2962. X            if (iBytesRead == iMsgLen) {
  2963. X            pbMsg.iLen = iBytesRead;
  2964. X            pbMsg.sMessage = TALK_BUFFER;
  2965. X            
  2966. X            (*TALK_MSG_FUNC) (&pbMsg);
  2967. X            break;
  2968. X            }
  2969. X            }
  2970. X
  2971. X        /** spin and wait for remaining data.
  2972. X         ** there is a minimal possibility of deadlock
  2973. X         ** introduced here.
  2974. X         ** situations that may cause spinning to deadlock:
  2975. X         ** 1. sending an oversized message to yourself.
  2976. X         ** 2. sending an oversized message to a process
  2977. X         **    that is simultaneously sending an oversized
  2978. X         **    message to you.
  2979. X         ** Assumption: oversized messages are infrequent.
  2980. X         **/
  2981. X        else if (iBytesRead > 0 && iErr == TALK_LISTEN_BLOCKED) {
  2982. X#ifndef OPTIMAL
  2983. X            if (TALK_BUGS)
  2984. X            fprintf(stderr, "listen %s: spinning on partial message..\n", WHOAMI);
  2985. X#endif
  2986. X            iErr = VEOS_SUCCESS;
  2987. X            }
  2988. X        }
  2989. X        }
  2990. X
  2991. X    } while (iErr == VEOS_SUCCESS);
  2992. X    
  2993. X    return(iErr);
  2994. X    
  2995. X    } /* Talk_RetrieveMessages */
  2996. X/****************************************************************************************/
  2997. X
  2998. X
  2999. X
  3000. X/****************************************************************************************
  3001. X * Talk_ThrowMessages                                    */
  3002. X
  3003. XTVeosErr Talk_ThrowMessages(pSpeakNode, pDirty)
  3004. X    TPSpeakNode        pSpeakNode;
  3005. X    boolean        *pDirty;
  3006. X{
  3007. X    TVeosErr        iErr = VEOS_FAILURE;
  3008. X    
  3009. X    *pDirty = FALSE;
  3010. X
  3011. X    if (pSpeakNode->pMessageQ) {        /* any messages? */
  3012. X    
  3013. X    if (pSpeakNode->iConnType == TALK_SOCK_CONN)
  3014. X        iErr = Talk_SendMsgsOverNet(pSpeakNode);
  3015. X
  3016. X    else if (pSpeakNode->iConnType == TALK_SHMEM_CONN)
  3017. X        iErr = ShMem_WriteMessages(pSpeakNode);
  3018. X
  3019. X
  3020. X    /** mark this connection for pending messages **/
  3021. X
  3022. X    if (pSpeakNode->pMessageQ)
  3023. X        *pDirty = TRUE;
  3024. X    }
  3025. X    
  3026. X    return(iErr);
  3027. X    
  3028. X    } /* Talk_ThrowMessages */
  3029. X/****************************************************************************************/
  3030. X
  3031. X
  3032. X
  3033. X/****************************************************************************************/
  3034. XTVeosErr Talk_SendMsgsOverNet(pSpeakNode)
  3035. X    TPSpeakNode        pSpeakNode;
  3036. X{
  3037. X    int            iLen, iMsgLen, iBytesWritten;
  3038. X    TPMessageNode    pSaveLink;
  3039. X    char        *pFinger;
  3040. X    int            iSocketFD;
  3041. X    TVeosErr        iErr = VEOS_SUCCESS;
  3042. X    
  3043. X    iSocketFD = pSpeakNode->iSocketFD;
  3044. X    
  3045. X    /** dispatch message sending...
  3046. X     ** oldest jobs first to enforce sequencing
  3047. X     **/        
  3048. X    
  3049. X    do {
  3050. X    /** attempt to transmit oldest message **/
  3051. X    
  3052. X    pFinger = pSpeakNode->pMessageQ->sMessage;
  3053. X    iMsgLen = pSpeakNode->pMessageQ->iMsgLen;
  3054. X    iBytesWritten = 0;
  3055. X
  3056. X    while (iErr == VEOS_SUCCESS) {
  3057. X
  3058. X         
  3059. X        /** transmit the message **/
  3060. X
  3061. X        iLen = iMsgLen - iBytesWritten;
  3062. X        iErr = Sock_Transmit(iSocketFD, pFinger, &iLen);
  3063. X#ifndef OPTIMAL        
  3064. X        if (TALK_BUGS) {
  3065. X            fprintf(stderr, "speak %s: transmit sent %d bytes, talk: %d, sys: %d\n",
  3066. X                WHOAMI, iLen, iErr, errno);
  3067. X            }
  3068. X#endif        
  3069. X
  3070. X        if (iErr == VEOS_SUCCESS) {
  3071. X
  3072. X        iBytesWritten += iLen;
  3073. X        pFinger += iLen;
  3074. X
  3075. X        if (iBytesWritten == iMsgLen) {
  3076. X
  3077. X            /** dequeue this message from connection record **/
  3078. X            
  3079. X            DUMP(pSpeakNode->pMessageQ->sMessage);
  3080. X            
  3081. X            pSaveLink = pSpeakNode->pMessageQ->pLink;
  3082. X            Shell_ReturnBlock(pSpeakNode->pMessageQ,
  3083. X                      sizeof(TMessageNode), "message node");
  3084. X            pSpeakNode->pMessageQ = pSaveLink;
  3085. X
  3086. X            break;
  3087. X            }
  3088. X        }
  3089. X
  3090. X        /** spin and wait for line to free.
  3091. X         ** there is a minimal possibility of deadlock
  3092. X         ** introduced here.
  3093. X         ** situations that may cause spinning to deadlock:
  3094. X         ** 1. sending an oversized message to yourself.
  3095. X         ** 2. sending an oversized message to a process
  3096. X         **    that is simultaneously sending an oversized
  3097. X         **    message to you.
  3098. X         ** Assumption: oversized messages are infrequent.
  3099. X         **/
  3100. X        else if (iBytesWritten > 0 && iErr == TALK_SPEAK_BLOCKED) {
  3101. X#ifndef OPTIMAL
  3102. X        if (TALK_BUGS)
  3103. X            fprintf(stderr, "speak %s: spinning on partial message..\n", WHOAMI);
  3104. X#endif
  3105. X        iErr = VEOS_SUCCESS;
  3106. X        }
  3107. X
  3108. X        } /* while more to write */
  3109. X    
  3110. X
  3111. X    } while (pSpeakNode->pMessageQ);
  3112. X
  3113. X    return(iErr);
  3114. X
  3115. X    } /* Talk_SendMsgsOverNet */
  3116. X/****************************************************************************************/
  3117. X
  3118. X
  3119. X
  3120. X/****************************************************************************************
  3121. X * Talk_AddSpeakJob                                    */
  3122. X
  3123. XTVeosErr Talk_AddSpeakJob(pDestNode, pMsgBlock)
  3124. X    TPSpeakNode        pDestNode;
  3125. X    TPMsgRec        pMsgBlock;
  3126. X{
  3127. X    TVeosErr        iErr;
  3128. X    TPMessageNode    pNewJob;
  3129. X    THMessageNode    hFinger;
  3130. X    
  3131. X    /** allocate new outgoing message job record **/
  3132. X    
  3133. X    iErr = Shell_NewBlock(sizeof(TMessageNode), &pNewJob, "message node");
  3134. X    if (iErr == VEOS_SUCCESS) {
  3135. X    
  3136. X
  3137. X    /** setup job record **/
  3138. X
  3139. X    if (NEWPTR(pNewJob->sMessage, char *, pMsgBlock->iLen + 4)) {
  3140. X        
  3141. X        /** insert length code at front of message **/
  3142. X        *(long *) pNewJob->sMessage = htonl(pMsgBlock->iLen);
  3143. X        
  3144. X        bcopy(pMsgBlock->sMessage, pNewJob->sMessage + 4, pMsgBlock->iLen);
  3145. X        pNewJob->iMsgLen = pMsgBlock->iLen + 4;
  3146. X        pNewJob->pLink = nil;
  3147. X    
  3148. X        /** append new job to destination's message queue **/
  3149. X        
  3150. X        hFinger = &pDestNode->pMessageQ;
  3151. X        while (*hFinger)
  3152. X        hFinger = &(*hFinger)->pLink;
  3153. X        
  3154. X        *hFinger = pNewJob;
  3155. X        
  3156. X        iErr = VEOS_SUCCESS;
  3157. X        }
  3158. X    }
  3159. X
  3160. X    
  3161. X    if (iErr != VEOS_SUCCESS) {
  3162. X    
  3163. X    /** cleanup any mess **/
  3164. X    
  3165. X    if (pNewJob) {
  3166. X        if (pNewJob->sMessage)
  3167. X        DUMP(pNewJob->sMessage);
  3168. X        Shell_ReturnBlock(pNewJob, sizeof(TMessageNode), "message node");
  3169. X        }
  3170. X    }
  3171. X    
  3172. X    return(iErr);
  3173. X    
  3174. X    } /* Talk_AddSpeakJob */
  3175. X/****************************************************************************************/
  3176. X
  3177. X
  3178. X
  3179. X/****************************************************************************************/
  3180. XTVeosErr Talk_DummyMsgHandler(pMsgRec)
  3181. X    TPMsgRec        pMsgRec;
  3182. X{
  3183. X    char        *pBuf;
  3184. X    
  3185. X    if (TALK_BUGS) {
  3186. X    fprintf(stderr, "listen %s: message not converted.\n", WHOAMI);
  3187. X    }    
  3188. X
  3189. X    return(VEOS_SUCCESS);
  3190. X
  3191. X    } /* Talk_DummyMsgHandler */
  3192. X/****************************************************************************************/
  3193. X
  3194. X
  3195. X#ifdef banana
  3196. Xint Talk_ConnectTrap();
  3197. X
  3198. X/****************************************************************************************/
  3199. Xint Talk_ConnectTrap(iSignal, iCode, context, pAddr)
  3200. X    int            iSignal, iCode;
  3201. X    struct sigcontext    *context;
  3202. X    char        *pAddr;
  3203. X{
  3204. X    if (iSignal == SIGIO)
  3205. X    NEW_CONN = TRUE;
  3206. X
  3207. X    return(0);
  3208. X    }
  3209. X/****************************************************************************************/
  3210. X#endif
  3211. X
  3212. X
  3213. X
  3214. X
  3215. X
  3216. X
  3217. X
  3218. X
  3219. END_OF_FILE
  3220. if test 24919 -ne `wc -c <'src/kernel_current/talk/talk.c'`; then
  3221.     echo shar: \"'src/kernel_current/talk/talk.c'\" unpacked with wrong size!
  3222. fi
  3223. # end of 'src/kernel_current/talk/talk.c'
  3224. fi
  3225. echo shar: End of archive 11 \(of 16\).
  3226. cp /dev/null ark11isdone
  3227. MISSING=""
  3228. for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
  3229.     if test ! -f ark${I}isdone ; then
  3230.     MISSING="${MISSING} ${I}"
  3231.     fi
  3232. done
  3233. if test "${MISSING}" = "" ; then
  3234.     echo You have unpacked all 16 archives.
  3235.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  3236. else
  3237.     echo You still need to unpack the following archives:
  3238.     echo "        " ${MISSING}
  3239. fi
  3240. ##  End of shell archive.
  3241. exit 0
  3242.