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