home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 4 / AACD04.ISO / AACD / Programming / Python / Source / Modules / AmigaExecmodule.c next >
Encoding:
C/C++ Source or Header  |  1999-10-24  |  9.6 KB  |  470 lines

  1.  
  2. /********************************************************************
  3.  
  4.     Amiga Exec module. ('amiga_exec')
  5.  
  6.     Provides access to various lowlevel Amiga Exec functions.
  7.  
  8. -----------------------------------------------
  9.     (c) 1999 Irmen de Jong.
  10.  
  11.     History:
  12.  
  13.     4-aug-99   Created. BETA!
  14.  
  15.  
  16. Module members:
  17.  
  18.     error         -- Exeption string object.  ('amiga_exec.error')
  19.     list_MsgPorts -- function returning list of known public message ports.
  20.     CreateMsgPort -- function returning a new MsgPort object.
  21.     FindPort      -- function returning an existing public MsgPort object, or None.
  22.  
  23. MsgPort object members:
  24.  
  25.     name        -- attribute, name of the port (RO)
  26.     signal      -- attribute, signal mask of the MsgPort's sigbit (RO)
  27.     close       -- function, closes the port
  28.     wait        -- function, waits for message to arrive
  29.     getmsg      -- function, returns a received message as a string.
  30.     putmsg      -- function, puts a new message on the port.
  31.  
  32. **************************************************************************/
  33.  
  34. #include <stdio.h>
  35. #include <exec/types.h>
  36. #include <exec/memory.h>
  37. #include <exec/ports.h>
  38. #include <exec/execbase.h>
  39. #include <dos/dos.h>
  40. #include <proto/exec.h>
  41. #include "Python.h"
  42.  
  43. #define MAX_PORTNAME_LEN 80
  44.  
  45. struct DataMessage
  46. {
  47.     struct Message m;
  48.     char data[0];
  49. };
  50.  
  51. typedef struct {
  52.     PyObject_HEAD
  53.     struct MsgPort *port;
  54.     struct MsgPort *replyPort;
  55.     char name[MAX_PORTNAME_LEN];
  56.     int fromExisting;
  57. } MsgPortobject;
  58.  
  59. static PyObject *error;    // Exception
  60.  
  61. /* Prototypes for functions defined */
  62. static BOOL Valid_Port(MsgPortobject *mpo);
  63. static void DeleteMsgPortSafely(struct MsgPort *port, int noreply);
  64.  
  65.  
  66. ///*** MSGPORT OBJECT MEMBER FUNCTIONS ***/
  67.  
  68. static BOOL Valid_Port(MsgPortobject *mpo)
  69. {
  70.     if(mpo->port) return TRUE;
  71.     PyErr_SetString(error,"closed port");
  72.     return FALSE;
  73. }
  74.  
  75. static void DeleteMsgPortSafely(struct MsgPort *port, int noreply)
  76. {
  77.     if(port)
  78.     {
  79.         struct Message *msg;
  80.  
  81.         if(port->mp_Node.ln_Name)
  82.             RemPort(port);
  83.  
  84.         while(msg = GetMsg(port))
  85.         {
  86.             if(msg->mn_ReplyPort && !noreply)
  87.                 ReplyMsg(msg);
  88.         }        
  89.         DeleteMsgPort(port);
  90.     }
  91. }
  92.  
  93. static PyObject *port_close(MsgPortobject *mpo, PyObject *args)
  94. {
  95.     if(!PyArg_NoArgs(args)) return NULL;
  96.  
  97.     if(mpo->fromExisting)
  98.     {
  99.         PyErr_SetString(error,"I don't own this port");
  100.         return NULL;
  101.     }
  102.     DeleteMsgPortSafely(mpo->port,0);
  103.     mpo->port=NULL;
  104.     DeleteMsgPortSafely(mpo->replyPort,1);
  105.     mpo->replyPort=NULL;
  106.     Py_INCREF(Py_None);
  107.     return Py_None;
  108. }
  109.  
  110. static PyObject *port_wait(MsgPortobject *mpo, PyObject *args)
  111. {
  112.     if(!PyArg_NoArgs(args)) return NULL;
  113.  
  114.     if(Valid_Port(mpo))
  115.     {
  116.         ULONG sigs = (1<<mpo->port->mp_SigBit) | SIGBREAKF_CTRL_C;
  117.         sigs = Wait(sigs);   /* XXX Abort with ^C */
  118.         if(sigs & SIGBREAKF_CTRL_C)
  119.         {
  120.             PyErr_SetNone(PyExc_KeyboardInterrupt);
  121.             return NULL;
  122.         }
  123.  
  124.         Py_INCREF(Py_None);
  125.         return Py_None;
  126.     } else return NULL;
  127. }
  128.  
  129. static PyObject *port_getmsg(MsgPortobject *mpo, PyObject *args)
  130. {
  131.     int blocking = 1;
  132.     int async = 0;
  133.  
  134.  
  135.     if (!PyArg_ParseTuple(args, "|ii", &blocking, &async))
  136.         return NULL;
  137.  
  138.     if(Valid_Port(mpo))
  139.     {
  140.         struct DataMessage *msg;
  141.  
  142.         if(blocking)
  143.         {
  144.             /* Wait() only if there is no message on the port */
  145.             
  146.             if(IsListEmpty(&mpo->port->mp_MsgList))
  147.             {
  148.                 ULONG sig;
  149.                 sig = Wait((1<<mpo->port->mp_SigBit) | SIGBREAKF_CTRL_C);   /* XXX Abort with ^C */
  150.                 if(sig & SIGBREAKF_CTRL_C)
  151.                 {
  152.                     PyErr_SetNone(PyExc_KeyboardInterrupt);
  153.                     return NULL;
  154.                 }
  155.                 else
  156.                 {
  157.                     msg=(struct DataMessage*)GetMsg(mpo->port);
  158.                 }
  159.             }
  160.             else
  161.             {
  162.                 msg=(struct DataMessage*)GetMsg(mpo->port);
  163.             }
  164.         }
  165.         else
  166.         {
  167.             /* non-blocking */
  168.             msg=(struct DataMessage*)GetMsg(mpo->port);
  169.         }
  170.  
  171.         if(msg)
  172.         {
  173.             PyObject *str;
  174.             int datalen = msg->m.mn_Length - sizeof(struct Message);
  175.             str = PyString_FromStringAndSize(msg->data,datalen);
  176.             if(async)
  177.             {
  178.                 // we should not reply, and deallocate the message ourselves
  179.                 FreeMem(msg,msg->m.mn_Length);
  180.             }
  181.             else if(msg->m.mn_ReplyPort)
  182.             {
  183.                 // reply the message and let the sender deallocate the storage
  184.                 ReplyMsg(&msg->m);
  185.             }
  186.             return str;
  187.         }
  188.  
  189.         Py_INCREF(Py_None);
  190.         return Py_None;
  191.     } else return NULL;
  192. }
  193.  
  194. static PyObject *port_putmsg(MsgPortobject *mpo, PyObject *args)
  195. {
  196.     char *str;
  197.     int stringlen;
  198.     int async = 0;
  199.  
  200.     if (!PyArg_ParseTuple(args, "s#|i", &str, &stringlen, &async))
  201.         return NULL;
  202.  
  203.     if(Valid_Port(mpo))
  204.     {
  205.         struct DataMessage *msg;
  206.         ULONG allocsize = sizeof(struct Message)+stringlen;
  207.         if(msg = (struct DataMessage*) AllocMem(allocsize, MEMF_ANY))
  208.         {
  209.             memset(&msg->m,0,sizeof(struct Message));
  210.             msg->m.mn_Node.ln_Type = NT_MESSAGE;
  211.             memcpy(msg->data,str,stringlen);
  212.             msg->m.mn_Length = allocsize;
  213.  
  214.             if(async)
  215.             {
  216.                 /* no reply, don't free msg */
  217.                 msg->m.mn_ReplyPort = NULL;
  218.                 PutMsg(mpo->port, &msg->m);
  219.             }
  220.             else
  221.             {
  222.                 /* we should wait for a reply and then free the message */
  223.                 ULONG sigs;
  224.                 msg->m.mn_ReplyPort = mpo->replyPort;
  225.                 PutMsg(mpo->port,&msg->m);
  226.                 sigs = Wait((1<<msg->m.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C);   /* XXX Abort with ^C */
  227.                 if(sigs & SIGBREAKF_CTRL_C)
  228.                 {
  229.                     PyErr_SetNone(PyExc_KeyboardInterrupt);
  230.                     return NULL;
  231.                 }
  232.                 (void)GetMsg(msg->m.mn_ReplyPort);
  233.                 FreeMem(msg,msg->m.mn_Length);
  234.             }
  235.             Py_INCREF(Py_None);
  236.             return Py_None;
  237.         }
  238.         else return PyErr_NoMemory();
  239.     }
  240.     return NULL;
  241. }
  242.  
  243. static struct PyMethodDef port_methods[] = {
  244.     {"close", (PyCFunction)port_close, 0},
  245.     {"wait", (PyCFunction)port_wait, 0},
  246.     {"getmsg", (PyCFunction)port_getmsg, 1},
  247.     {"putmsg", (PyCFunction)port_putmsg, 1},
  248.     {NULL,      NULL}       /* sentinel */
  249. };
  250.  
  251. static void
  252. port_dealloc(MsgPortobject *self)         // `destructor'
  253. {
  254.     if(!self->fromExisting) DeleteMsgPortSafely(self->port,0);
  255.     DeleteMsgPortSafely(self->replyPort,1);
  256.     PyMem_DEL(self);
  257. }
  258.  
  259. static PyObject *
  260. port_getattr(MsgPortobject *mpo, char *name)
  261. {
  262.     if(mpo->port)
  263.     {
  264.         if (strcmp(name, "name")==0)
  265.         {
  266.             if(!mpo->port->mp_Node.ln_Name)
  267.             {
  268.                 // port has no name
  269.                 PyErr_SetString(PyExc_AttributeError,name); return NULL;
  270.             }   
  271.             return PyString_FromString(mpo->port->mp_Node.ln_Name);
  272.         }
  273.         else if(strcmp(name,"signal")==0)
  274.             return PyInt_FromLong(1<<mpo->port->mp_SigBit);
  275.     }
  276.     return Py_FindMethod(port_methods, (PyObject *)mpo, name);
  277. }
  278.  
  279. static PyObject *
  280. port_repr(MsgPortobject *mpo)
  281. {
  282.     char buf[200];
  283.     char *w;
  284.  
  285.     if(!(mpo->port))
  286.         w="(closed)";
  287.     else if(!mpo->port->mp_Node.ln_Name)
  288.         w="(private)";
  289.     else
  290.         w=mpo->port->mp_Node.ln_Name;
  291.     sprintf(buf,"<MsgPort %s at %lx>",w,(long)mpo);
  292.     return PyString_FromString(buf);
  293. }
  294.  
  295. static PyTypeObject MsgPortType = {
  296.     PyObject_HEAD_INIT(&PyType_Type)
  297.     0,          /*ob_size*/
  298.     "MsgPort",        /*tp_name*/
  299.     sizeof(MsgPortobject),    /*tp_size*/
  300.     0,          /*tp_itemsize*/
  301.     /* methods */
  302.     (destructor)port_dealloc, /*tp_dealloc*/
  303.     0,          /*tp_print*/
  304.     (getattrfunc)port_getattr, /*tp_getattr*/
  305.     (setattrfunc)0, /*tp_setattr*/
  306.     0,          /*tp_compare*/
  307.     (reprfunc)port_repr,        /*tp_repr*/
  308. };
  309.  
  310.  
  311. ///
  312.  
  313.  
  314. ///******************************** MODULE FUNCTIONS ************************/
  315.  
  316. static PyObject *
  317. amiga_exec_FindPort(PyObject *self, PyObject *args)
  318. {
  319.     char *name;
  320.     struct MsgPort *port;
  321.  
  322.     if (!PyArg_ParseTuple(args, "s", &name))
  323.         return NULL;
  324.  
  325.     if(port=FindPort(name))
  326.     {
  327.         MsgPortobject *mpo;
  328.         if(mpo = PyObject_NEW(MsgPortobject, &MsgPortType))
  329.         {
  330.             mpo->port = port;
  331.             mpo->fromExisting = 1;
  332.             if(mpo->replyPort = CreateMsgPort())
  333.             {
  334.                 return (PyObject*) mpo;
  335.             }
  336.             /* could not create replyport */
  337.             Py_DECREF(mpo);
  338.             return PyErr_NoMemory();
  339.         }
  340.         else return NULL;
  341.     }
  342.     PyErr_SetString(error,"Can't find MsgPort");
  343.     return NULL;
  344. }
  345.  
  346. static PyObject *
  347. amiga_exec_listMsgPorts(PyObject *self, PyObject *args)
  348. {
  349.     PyObject *list;
  350.     PyObject *item;
  351.  
  352.     if (!PyArg_ParseTuple(args, "")) return NULL;
  353.  
  354.     if(list = PyList_New(0))
  355.     {
  356.         struct Node *node;
  357.         int failed=0;
  358.         Forbid();
  359.         for (node = SysBase->PortList.lh_Head; node->ln_Succ; node = node->ln_Succ)
  360.         {
  361.             if(item = PyString_FromString(node->ln_Name))
  362.             {
  363.                 if(PyList_Append(list,item)!=0)
  364.                 {
  365.                     Py_DECREF(item);
  366.                     failed=1; break;
  367.                 }
  368.             }
  369.             else
  370.             {
  371.                 failed=1; break;
  372.             }
  373.         }
  374.         Permit();
  375.         if(failed)
  376.         {
  377.             Py_DECREF(list);
  378.             return PyErr_NoMemory();
  379.         }
  380.         return list;
  381.     }
  382.     else return NULL;
  383. }
  384.  
  385.  
  386. static PyObject *
  387. amiga_exec_CreateMsgPort(PyObject *self, PyObject *args)
  388. {
  389.     MsgPortobject *mpo;
  390.     char *name;
  391.     
  392.     if (!PyArg_ParseTuple(args, "z", &name))
  393.         return NULL;
  394.  
  395.     if(name)
  396.     {
  397.         if(strlen(name)>MAX_PORTNAME_LEN)
  398.         {
  399.             PyErr_SetString(error,"Portname too long");
  400.             return NULL;
  401.         }
  402.         if(name[0]=='\0')
  403.         {
  404.             name=NULL;
  405.         }
  406.     }
  407.  
  408.     if(name && FindPort(name))
  409.     {
  410.         PyErr_SetString(error,"Port already exists with this name");
  411.         return NULL;
  412.     }
  413.  
  414.     if(mpo = PyObject_NEW(MsgPortobject, &MsgPortType))
  415.     {
  416.         mpo->fromExisting=0;
  417.         if(mpo->port = CreateMsgPort())
  418.         {
  419.             if(name)
  420.             {
  421.                 strcpy(mpo->name,name);
  422.                 mpo->port->mp_Node.ln_Name = &(mpo->name[0]);
  423.                 AddPort(mpo->port);
  424.             }
  425.  
  426.             if(mpo->replyPort = CreateMsgPort())
  427.             {    
  428.                 /** all went OK! **/
  429.                 return (PyObject*) mpo;
  430.             }
  431.  
  432.             /** something went wrong, clean up **/
  433.             if(name)
  434.                 RemPort(mpo->port);
  435.  
  436.             DeleteMsgPortSafely(mpo->port,0);
  437.             mpo->port=NULL;
  438.         }
  439.         PyErr_SetString(error,"can't open port");
  440.  
  441.         PyMem_DEL(mpo); mpo=NULL;
  442.     }
  443.     return (PyObject*)mpo;
  444. }
  445.  
  446.  
  447. /*** FUNCTIONS FROM THE MODULE ***/
  448.  
  449. static struct PyMethodDef amiga_exec_global_methods[] = {
  450.     {"CreateMsgPort",  amiga_exec_CreateMsgPort, 1},
  451.     {"FindPort",  amiga_exec_FindPort, 1},
  452.     {"list_MsgPorts",  amiga_exec_listMsgPorts, 1},
  453.     {NULL,      NULL}       /* sentinel */
  454. };
  455. ///
  456.  
  457. void
  458. initamiga_exec Py_PROTO((void))
  459. {
  460.     PyObject *m, *d;
  461.  
  462.     m = Py_InitModule("amiga_exec", amiga_exec_global_methods);
  463.     d = PyModule_GetDict(m);
  464.  
  465.     /* Initialize error exception */
  466.     error = PyErr_NewException("amiga_exec.error", NULL, NULL);
  467.     if (error != NULL)
  468.         PyDict_SetItemString(d, "error", error);
  469. }
  470.