home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / MacPerl 5.1.3 / Mac_Perl_513_src / MacPerl5 / MPAEVTStream.cp < prev    next >
Encoding:
Text File  |  1996-10-21  |  13.0 KB  |  619 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Standalone Perl
  3. File        :    MPConsole.cp    -    Console interface for GUSI
  4. Author    :    Matthias Neeracher
  5. Language    :    MPW C/C++
  6.  
  7. $Log: MPConsole.cp,v $
  8. *********************************************************************/
  9.  
  10. #include <GUSIFile_P.h>
  11. #include <AEBuild.h>
  12.  
  13. #include "MPGlobals.h"
  14. #include "MPAEVTStream.h"
  15. #include "MPConsole.h"
  16.  
  17. #include <AEStream_CPlus.h>
  18.  
  19. extern "C" {
  20. #include <AESubDescs.h>
  21.  
  22. #include <ioctl.h>
  23. }
  24.  
  25. #undef open
  26.  
  27. class MPAEVTSocket;                             // That's what this file's all about
  28.  
  29. class MPAEVTSocket : public Socket    {        
  30.     friend class MPAEVTSocketDomain;    
  31.     
  32.                     MPAEVTSocket(OSType key, Boolean input, Boolean output);
  33.                     
  34.     virtual         ~MPAEVTSocket();
  35.     
  36.     OSType                        key;
  37.     Handle                        inData;
  38.     Handle                        outData;
  39.     Boolean                        eof;
  40.     Boolean                        nonblocking;
  41.     Boolean                        needy;
  42.     MPAEVTSocket *                next;
  43.     MPAEVTSocket *             prev;
  44. public:
  45.     virtual int    read(void * buffer, int buflen);
  46.     virtual int write(void * buffer, int buflen);
  47.     virtual int    fcntl(unsigned int cmd, int arg);
  48.     virtual void pre_select(Boolean wantRead, Boolean wantWrite, Boolean wantExcept);
  49.     virtual int select(Boolean * canRead, Boolean * canWrite, Boolean * exception);
  50.     virtual int    ioctl(unsigned int request, void *argp);
  51.     virtual int    isatty();
  52. };    
  53.  
  54. class MPAEVTSocketDomain : public FileSocketDomain {
  55.     friend class MPAEVTSocket;
  56.     
  57.     MPAEVTSocket *            Lookup(OSType key, Boolean input, Boolean output);
  58.     
  59.     MPAEVTSocket *            first;
  60.     OSType                    key;
  61.     OSType                    mode;
  62.     DescType                    saseClass;
  63.     DescType                    saseID;
  64.     AppleEvent                sase;
  65.     AEDesc                    target;
  66.     AEStream                    outputData;
  67.     AEDesc                    outputDirect;
  68.     short                        outputDataCount;
  69. public:
  70.     MPAEVTSocketDomain();
  71.     
  72.     virtual Boolean Yours(const GUSIFileRef & ref, Request request);
  73.     virtual Socket * open(const GUSIFileRef & ref, int oflag);
  74.     
  75.     void CollectOutput(AppleEvent * output);
  76.     void DistributeInput(const AppleEvent * input, long mode);
  77.     void KillInput();
  78.     void FlushInput();
  79.  
  80.     void         DoRead();
  81.     Boolean    MayRead();
  82.     
  83.     Boolean                    finish;
  84.     long                        received;
  85. };
  86.  
  87. MPAEVTSocketDomain    MPAEVTSockets;
  88.  
  89. #if !defined(powerc) && !defined(__powerc)
  90. #pragma segment MPAEVT
  91. #endif
  92.  
  93. /************************ MPAEVTSocket members ************************/
  94.  
  95. MPAEVTSocket::MPAEVTSocket(OSType key, Boolean input, Boolean output)
  96.     : key(key), needy(false), nonblocking(false)
  97. {
  98.     eof        =    !input || MPAEVTSockets.mode == 'BATC';
  99.     inData    =    input ? NewHandle(0) : nil;
  100.     outData    =    output ? NewHandle(0) : nil;
  101.     
  102.     if (!MPAEVTSockets.first) {
  103.         MPAEVTSockets.first    = this;
  104.         next                        = this;
  105.         prev                        = this;
  106.     } else {
  107.         next                         = MPAEVTSockets.first;
  108.         prev                         = MPAEVTSockets.first->prev;
  109.         next->prev                = this;
  110.         prev->next                 = this;
  111.     }
  112. }
  113.  
  114. MPAEVTSocket::~MPAEVTSocket()
  115. {
  116.     if (outData)
  117.         if (GetHandleSize(outData)) {
  118.             AEDesc    desc ;
  119.             
  120.             desc.descriptorType = 'TEXT';
  121.             desc.dataHandle     = outData;
  122.             
  123.             if (key == '----')
  124.                 MPAEVTSockets.outputDirect    =    desc;
  125.             else {
  126.                 MPAEVTSockets.outputData.WriteKey(key);
  127.                 MPAEVTSockets.outputData.WriteDesc(desc);
  128.                 ++MPAEVTSockets.outputDataCount;
  129.                 AEDisposeDesc(&desc);
  130.             }
  131.         } else
  132.             DisposeHandle(outData);
  133.             
  134.     if (inData)
  135.         DisposeHandle(inData);
  136.     
  137.     if (next == this)
  138.         MPAEVTSockets.first    = nil;
  139.     else {
  140.         MPAEVTSockets.first    = next;
  141.         next->prev                = prev;
  142.         prev->next                = next;
  143.     }
  144. }
  145.  
  146. int MPAEVTSocket::fcntl(unsigned int cmd, int arg)
  147. {
  148.     switch (cmd)    {
  149.     case F_GETFL:
  150.         if (nonblocking)
  151.             return FNDELAY;
  152.         else
  153.             return 0;
  154.     case F_SETFL:
  155.         if (arg & FNDELAY)
  156.             nonblocking = true;
  157.         else
  158.             nonblocking = false;
  159.  
  160.         return 0;
  161.     default:
  162.         return GUSI_error(EOPNOTSUPP);
  163.     }
  164. }
  165.  
  166. int MPAEVTSocket::ioctl(unsigned int request, void *argp)
  167. {
  168.     switch ((long) request)    {
  169.     case FIONBIO:
  170.         nonblocking    =    (Boolean) *(long *) argp;
  171.         
  172.         return 0;
  173.     case FIONREAD:
  174.         if (!inData)
  175.             return GUSI_error(ESHUTDOWN);
  176.         
  177.         *(unsigned long *) argp    = GetHandleSize(inData);
  178.         
  179.         return 0;
  180.     case FIOINTERACTIVE:
  181.         return 0;
  182.     default:
  183.         return GUSI_error(EOPNOTSUPP);
  184.     }
  185. }
  186.  
  187. int MPAEVTSocket::read(void * buffer, int buflen)
  188. {
  189.     if (!inData)
  190.         return GUSI_error(ESHUTDOWN);
  191.  
  192.     int    avail;
  193.     
  194.     while (1) {    
  195.         avail = int(GetHandleSize(inData));
  196.         
  197.         if (!avail)
  198.             if (eof)
  199.                 return 0;
  200.             else {
  201.                 needy = true;
  202.                 if (nonblocking)
  203.                     return GUSI_error(EWOULDBLOCK);
  204.                 else
  205.                     MPAEVTSockets.DoRead();
  206.             }
  207.         else
  208.             break;
  209.     }
  210.     
  211.     needy     = false;
  212.     buflen = min(avail, buflen);
  213.     
  214.     HLock(inData);
  215.     memcpy(buffer, *inData, buflen);
  216.     if (avail -= buflen)
  217.         memcpy(*inData, *inData+buflen, avail);
  218.     HUnlock(inData);
  219.     SetHandleSize(inData, avail);
  220.     
  221.     return buflen;
  222. }
  223.  
  224. int MPAEVTSocket::write(void * buffer, int buflen)
  225. {
  226.     if (!outData)
  227.         return GUSI_error(ESHUTDOWN);
  228.     else if (PtrAndHand(buffer, outData, buflen))
  229.         return GUSI_error(ENOMEM);
  230.     
  231.     return buflen;
  232. }
  233.  
  234. void MPAEVTSocket::pre_select(Boolean, Boolean, Boolean)
  235. {
  236.     needy = false;
  237. }
  238.  
  239. int MPAEVTSocket::select(Boolean * canRead, Boolean * canWrite, Boolean * exception)
  240. {
  241.     int        goodies     =     0;
  242.         
  243.     if (canRead)
  244.         if (inData)
  245.             if (*canRead = (GetHandleSize(inData) > 0 || eof))
  246.                 ++goodies;
  247.             else if (needy) {
  248.                 MPAEVTSockets.DoRead();
  249.                 if (*canRead = (GetHandleSize(inData) > 0 || eof))
  250.                     ++goodies;
  251.             } else
  252.                 needy = true;
  253.         else
  254.             *canRead = false;
  255.     
  256.     if (canWrite)
  257.         if (*canWrite = (outData != nil))
  258.             ++goodies;
  259.     
  260.     if (exception)
  261.         *exception = false;
  262.     
  263.     return goodies;
  264. }
  265.  
  266. int MPAEVTSocket::isatty()
  267. {
  268.     return 1;
  269. }
  270.  
  271. /********************* MPAEVTSocketDomain members **********************/
  272.  
  273. MPAEVTSocketDomain::MPAEVTSocketDomain()
  274.     :    FileSocketDomain(AF_UNSPEC, true, false), finish(false), first(nil), received(0)
  275. {
  276.     outputData.OpenRecord(typeAERecord);
  277. }
  278.  
  279. Boolean MPAEVTSocketDomain::Yours(const GUSIFileRef & ref, FileSocketDomain::Request request)
  280. {
  281.     if (ref.spec || (request != willOpen))
  282.         return false;
  283.     
  284.     if (
  285.             (ref.name[4] | 0x20) == 's'
  286.         && (ref.name[5] | 0x20) == 't' 
  287.         && (ref.name[6] | 0x20) == 'd'
  288.     ) {
  289.         if (!gRemoteControl)
  290.             return false;
  291.             
  292.         switch (ref.name[7] | 0x20) {
  293.         case 'i':
  294.             key = '----';
  295.             
  296.             return (ref.name[8] | 0x20) == 'n' && !ref.name[9];
  297.         case 'o':
  298.             key = '----';
  299.             
  300.             return    (ref.name[8] | 0x20) == 'u' 
  301.                     && (ref.name[9] | 0x20) == 't' 
  302.                     && !ref.name[10];
  303.         case 'e':
  304.             key = 'diag';
  305.             
  306.             return     (ref.name[8] | 0x20) == 'r' 
  307.                     && (ref.name[9] | 0x20) == 'r' 
  308.                     && !ref.name[10];
  309.         default:
  310.             return false;
  311.         }
  312.     } else if (!strncmp(ref.name+4, "AEVT", 4))
  313.         switch (ref.name[8]) {
  314.         case 0:
  315.             key = '----';
  316.         
  317.             return true;
  318.         case ':':
  319.             key = '    ';
  320.             
  321.             int len = strlen(ref.name+9);
  322.             
  323.             memcpy(&key, ref.name+9, len < 4 ? len : 4);
  324.             
  325.             return true;
  326.         }
  327.     
  328.     return false;
  329. }
  330.  
  331. Socket * MPAEVTSocketDomain::open(const GUSIFileRef &, int flags)
  332. {
  333.     return Lookup(key, !(flags & O_WRONLY), (flags & 3) != 0);
  334. }
  335.  
  336. Boolean MPAEVTSocketDomain::MayRead()
  337. {
  338.     return (mode == 'RCTL') || (mode == 'DPLX');
  339. }
  340.  
  341. void MPAEVTSocketDomain::DoRead()
  342. {
  343.     if (!MayRead())
  344.         KillInput();
  345.     else {    
  346.         long    oldReceived = received;
  347.         
  348.         if (sase.dataHandle) {
  349.             /* Send tickle event. */
  350.             OSErr            err;
  351.             AppleEvent    tickle;
  352.             AppleEvent    tickleReply;
  353.             
  354.             if (AECreateAppleEvent(saseClass, saseID, &target, 0, 0, &tickle))
  355.                 goto waitForData;
  356.             
  357.             AEKeyword    key;
  358.             AEDesc        desc;
  359.             
  360.             for (long index = 1; !AEGetNthDesc(&sase, index++, typeWildCard, &key, &desc);) {
  361.                 AEPutParamDesc(&tickle, key, &desc);
  362.                 AEDisposeDesc(&desc);
  363.             }
  364.             
  365.             if (mode == 'DPLX') {
  366.                 CollectOutput(&tickle);
  367.                 err = AESend(&tickle, &tickleReply, kAEWaitReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  368.                 DistributeInput(&tickleReply, 0);
  369.                 ++received;
  370.                 AEDisposeDesc(&tickleReply);
  371.             } else {
  372.                 err = AESend(&tickle, &tickleReply, kAENoReply, kAENormalPriority, kAEDefaultTimeout, nil, nil);
  373.             }
  374.             
  375.             AEDisposeDesc(&tickle);
  376.             
  377.             if (err) {
  378.                 KillInput();
  379.                 return;
  380.             }
  381.         }
  382.     waitForData:
  383.         while (!MPConsoleSpin(SP_STREAM_READ, 0) && oldReceived == received)
  384.             ;
  385.     }
  386. }
  387.  
  388. static void AEGetAttrOrParam(AEDesc * from, DescType keyword, void * into)
  389. {
  390.     Size         size;
  391.     DescType    type;
  392.  
  393.     if (AEGetAttributePtr(from, keyword, typeWildCard, &type, into, 4, &size))
  394.         if (!AEGetParamPtr(from, keyword, typeWildCard, &type, into, 4, &size))
  395.             AEDeleteParam(from, keyword);
  396. }
  397.  
  398. void MPAEVTSocketDomain::DistributeInput(const AppleEvent * input, long mode)
  399. {
  400.     AEDesc        desc;
  401.     AESubDesc    aes;
  402.     AESubDesc    item;
  403.     DescType        keyword;
  404.     
  405.     if (mode)
  406.         this->mode = mode;
  407.         
  408.     if (!AEGetParamDesc(input, 'INPT', typeAERecord, &desc)) {
  409.         AEDescToSubDesc(&desc, &aes);
  410.  
  411.         HLock(aes.dataHandle);
  412.         
  413.         long maxIndex = AECountSubDescItems(&aes);
  414.         
  415.         for (long index = 0; index++ < maxIndex; ) {
  416.             if (AEGetNthSubDesc(&aes, index, &keyword, &item))
  417.                 continue;
  418.                 
  419.             long                length;
  420.             
  421.             void *             data = AEGetSubDescData(&item, &length);
  422.             MPAEVTSocket * sock = Lookup(keyword, true, false);
  423.             
  424.             if (sock)
  425.                 if (AEGetSubDescType(&item) == typeNull)
  426.                     sock->eof = true;
  427.                 else if (sock->inData && length)
  428.                     PtrAndHand(data, sock->inData, length);
  429.         }
  430.         
  431.         AEDisposeDesc(&desc);
  432.     }
  433.     
  434.     if (!mode) {
  435.         if (!AEGetParamDesc(input, '----', typeWildCard, &desc)) {
  436.             MPAEVTSocket * sock = Lookup('----', true, false);
  437.         
  438.             if (sock)
  439.                 if (desc.descriptorType == typeNull)
  440.                     sock->eof = true;
  441.                 else if (sock->inData) {
  442.                     HLock(desc.dataHandle);
  443.                     HandAndHand(desc.dataHandle, sock->inData);
  444.                 }
  445.         
  446.             AEDisposeDesc(&desc);
  447.         }
  448.     } else {
  449.         AEDesc    doneDesc;
  450.         
  451.         if (AEGetParamDesc(input, 'SASE', typeAERecord, &sase))
  452.             if (mode = 'DPLX')
  453.                 AEBuild(&sase, "{evcl: McPL, evid: SASE}");
  454.         if (sase.dataHandle) {
  455.             AEGetAttributeDesc(input, keyAddressAttr, typeWildCard, &target);
  456.             AEGetAttrOrParam(&sase, keyEventClassAttr, &saseClass);
  457.             AEGetAttrOrParam(&sase, keyEventIDAttr, &saseID);
  458.         }
  459.         if (!AEGetParamDesc(input, 'DONE', typeBoolean, &doneDesc)
  460.          && **(Boolean **) doneDesc.dataHandle
  461.         )
  462.             this->mode = 'BATC';
  463.     }
  464. }
  465.  
  466. void MPAEVTSocketDomain::KillInput()
  467. {
  468.     int                runs = 0;
  469.     MPAEVTSocket * sock = first;
  470.  
  471.     if (sock)
  472.         while ((runs += sock == first) < 2) {
  473.             if (sock->needy) 
  474.                 sock->eof = true;
  475.             
  476.             sock = sock->next;
  477.         }
  478. }
  479.  
  480. void MPAEVTSocketDomain::FlushInput()
  481. {
  482.     int                runs = 0;
  483.     MPAEVTSocket * sock = first;
  484.  
  485.     if (sock)
  486.         while ((runs += sock == first) < 2) {
  487.             if (sock->inData) 
  488.                 SetHandleSize(sock->inData, 0);
  489.             
  490.             sock = sock->next;
  491.         }
  492.     AEDisposeDesc(&sase);
  493.     AEDisposeDesc(&target);
  494. }
  495.  
  496. void MPAEVTSocketDomain::CollectOutput(AppleEvent * output)
  497. {
  498.     OSErr                err;
  499.     AEStream         want;
  500.     AEDesc            desc;
  501.     int                wantCount = 0;
  502.     int                runs = 0;
  503.     MPAEVTSocket * sock = first;
  504.     
  505.     desc.descriptorType = 'TEXT';
  506.     
  507.     want.OpenList();
  508.     
  509.     if (sock)
  510.         while ((runs += sock == first) < 2) {
  511.             if (sock->outData && GetHandleSize(sock->outData)) {
  512.                 desc.dataHandle = sock->outData;
  513.                 if (sock->key == '----')
  514.                     if (!AEPutParamDesc(output, '----', &desc))
  515.                         SetHandleSize(sock->outData, 0);
  516.                     else 
  517.                         return;                            // This is sort of disastrous
  518.                 else if (outputData.WriteKey(sock->key) || outputData.WriteDesc(desc))                
  519.                     return;                                //     ... so is this.
  520.                 else 
  521.                     ++outputDataCount;
  522.             }
  523.             if (sock->inData && sock->needy)
  524.                 if (!want.WriteDesc(typeEnumerated, &sock->key, 4))
  525.                     ++wantCount;
  526.             
  527.             sock = sock->next;
  528.         }
  529.     
  530.     if (outputDirect.dataHandle) {
  531.         err = AEPutParamDesc(output, '----', &outputDirect);
  532.         AEDisposeDesc(&outputDirect);
  533.     
  534.         if (err)
  535.             return;
  536.     }
  537.     
  538.     if (!(err = outputData.CloseRecord()))
  539.         err = outputData.Close(&desc);
  540.     
  541.     AEStream_Open(&outputData);
  542.     outputData.OpenRecord(typeAERecord);
  543.     
  544.     if (outputDataCount) {
  545.         outputDataCount = 0;
  546.         if (!err) {
  547.             err = AEPutParamDesc(output, 'OUTP', &desc);
  548.             AEDisposeDesc(&desc);
  549.             
  550.             if (err)
  551.                 return;    // Death before Dishonour
  552.         } else
  553.             return;
  554.     } else if (!err)
  555.         AEDisposeDesc(&desc);
  556.         
  557.     if (!want.CloseList() && wantCount) {
  558.         if (!want.Close(&desc)) {
  559.             AEPutParamDesc(output, 'WANT', &desc);
  560.             AEDisposeDesc(&desc);
  561.         } 
  562.     } else
  563.         want.Close();
  564.     
  565.     AEPutParamPtr(output, 'DONE', typeBoolean, (Ptr) &finish, 1);
  566.     
  567.     if (sock)    
  568.         for (runs = 0; (runs += sock == first) < 2; sock = sock->next) 
  569.             if (sock->outData) 
  570.                 SetHandleSize(sock->outData, 0);
  571. }
  572.  
  573. MPAEVTSocket * MPAEVTSocketDomain::Lookup(OSType key, Boolean input, Boolean output)
  574. {
  575.     int                runs = 0;
  576.     MPAEVTSocket * sock = first;
  577.     
  578.     if (sock)
  579.         while ((runs += sock == first) < 2)
  580.             if (sock->key == key) {
  581.                 if (input && !sock->inData)
  582.                     sock->inData = NewHandle(0);
  583.                 if (output && !sock->outData)
  584.                     sock->outData = NewHandle(0);
  585.                 
  586.                 return sock;
  587.             } else
  588.                 sock = sock->next;
  589.     
  590.     return new MPAEVTSocket(key, input, output);
  591. }
  592.  
  593. /********************* Interface routines **********************/
  594.  
  595. pascal OSErr Relay(const AppleEvent * inData, AppleEvent * outData, long refCon)
  596. {
  597.     ++MPAEVTSockets.received;
  598.     
  599.     if (inData)
  600.         MPAEVTSockets.DistributeInput(inData, refCon);
  601.     if (outData)
  602.         MPAEVTSockets.CollectOutput(outData);
  603.         
  604.     return noErr;
  605. }
  606.  
  607. pascal void FlushAEVTs(AppleEvent * outData)
  608. {
  609.     if (outData)
  610.         MPAEVTSockets.CollectOutput(outData);
  611.     else {
  612.         MPAEVTSockets.finish = true;
  613.         MPAEVTSockets.DoRead();
  614.         MPAEVTSockets.finish = false;
  615.     }
  616.     MPAEVTSockets.FlushInput();
  617. }
  618.  
  619.