home *** CD-ROM | disk | FTP | other *** search
-
- /********************************************************************
-
- Amiga Exec module. ('amiga_exec')
-
- Provides access to various lowlevel Amiga Exec functions.
-
- -----------------------------------------------
- (c) 1999 Irmen de Jong.
-
- History:
-
- 4-aug-99 Created. BETA!
-
-
- Module members:
-
- error -- Exeption string object. ('amiga_exec.error')
- list_MsgPorts -- function returning list of known public message ports.
- CreateMsgPort -- function returning a new MsgPort object.
- FindPort -- function returning an existing public MsgPort object, or None.
-
- MsgPort object members:
-
- name -- attribute, name of the port (RO)
- signal -- attribute, signal mask of the MsgPort's sigbit (RO)
- close -- function, closes the port
- wait -- function, waits for message to arrive
- getmsg -- function, returns a received message as a string.
- putmsg -- function, puts a new message on the port.
-
- **************************************************************************/
-
- #include <stdio.h>
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <exec/ports.h>
- #include <exec/execbase.h>
- #include <dos/dos.h>
- #include <proto/exec.h>
- #include "Python.h"
-
- #define MAX_PORTNAME_LEN 80
-
- struct DataMessage
- {
- struct Message m;
- char data[0];
- };
-
- typedef struct {
- PyObject_HEAD
- struct MsgPort *port;
- struct MsgPort *replyPort;
- char name[MAX_PORTNAME_LEN];
- int fromExisting;
- } MsgPortobject;
-
- static PyObject *error; // Exception
-
- /* Prototypes for functions defined */
- static BOOL Valid_Port(MsgPortobject *mpo);
- static void DeleteMsgPortSafely(struct MsgPort *port, int noreply);
-
-
- ///*** MSGPORT OBJECT MEMBER FUNCTIONS ***/
-
- static BOOL Valid_Port(MsgPortobject *mpo)
- {
- if(mpo->port) return TRUE;
- PyErr_SetString(error,"closed port");
- return FALSE;
- }
-
- static void DeleteMsgPortSafely(struct MsgPort *port, int noreply)
- {
- if(port)
- {
- struct Message *msg;
-
- if(port->mp_Node.ln_Name)
- RemPort(port);
-
- while(msg = GetMsg(port))
- {
- if(msg->mn_ReplyPort && !noreply)
- ReplyMsg(msg);
- }
- DeleteMsgPort(port);
- }
- }
-
- static PyObject *port_close(MsgPortobject *mpo, PyObject *args)
- {
- if(!PyArg_NoArgs(args)) return NULL;
-
- if(mpo->fromExisting)
- {
- PyErr_SetString(error,"I don't own this port");
- return NULL;
- }
- DeleteMsgPortSafely(mpo->port,0);
- mpo->port=NULL;
- DeleteMsgPortSafely(mpo->replyPort,1);
- mpo->replyPort=NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
-
- static PyObject *port_wait(MsgPortobject *mpo, PyObject *args)
- {
- if(!PyArg_NoArgs(args)) return NULL;
-
- if(Valid_Port(mpo))
- {
- ULONG sigs = (1<<mpo->port->mp_SigBit) | SIGBREAKF_CTRL_C;
- sigs = Wait(sigs); /* XXX Abort with ^C */
- if(sigs & SIGBREAKF_CTRL_C)
- {
- PyErr_SetNone(PyExc_KeyboardInterrupt);
- return NULL;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
- } else return NULL;
- }
-
- static PyObject *port_getmsg(MsgPortobject *mpo, PyObject *args)
- {
- int blocking = 1;
- int async = 0;
-
-
- if (!PyArg_ParseTuple(args, "|ii", &blocking, &async))
- return NULL;
-
- if(Valid_Port(mpo))
- {
- struct DataMessage *msg;
-
- if(blocking)
- {
- /* Wait() only if there is no message on the port */
-
- if(IsListEmpty(&mpo->port->mp_MsgList))
- {
- ULONG sig;
- sig = Wait((1<<mpo->port->mp_SigBit) | SIGBREAKF_CTRL_C); /* XXX Abort with ^C */
- if(sig & SIGBREAKF_CTRL_C)
- {
- PyErr_SetNone(PyExc_KeyboardInterrupt);
- return NULL;
- }
- else
- {
- msg=(struct DataMessage*)GetMsg(mpo->port);
- }
- }
- else
- {
- msg=(struct DataMessage*)GetMsg(mpo->port);
- }
- }
- else
- {
- /* non-blocking */
- msg=(struct DataMessage*)GetMsg(mpo->port);
- }
-
- if(msg)
- {
- PyObject *str;
- int datalen = msg->m.mn_Length - sizeof(struct Message);
- str = PyString_FromStringAndSize(msg->data,datalen);
- if(async)
- {
- // we should not reply, and deallocate the message ourselves
- FreeMem(msg,msg->m.mn_Length);
- }
- else if(msg->m.mn_ReplyPort)
- {
- // reply the message and let the sender deallocate the storage
- ReplyMsg(&msg->m);
- }
- return str;
- }
-
- Py_INCREF(Py_None);
- return Py_None;
- } else return NULL;
- }
-
- static PyObject *port_putmsg(MsgPortobject *mpo, PyObject *args)
- {
- char *str;
- int stringlen;
- int async = 0;
-
- if (!PyArg_ParseTuple(args, "s#|i", &str, &stringlen, &async))
- return NULL;
-
- if(Valid_Port(mpo))
- {
- struct DataMessage *msg;
- ULONG allocsize = sizeof(struct Message)+stringlen;
- if(msg = (struct DataMessage*) AllocMem(allocsize, MEMF_ANY))
- {
- memset(&msg->m,0,sizeof(struct Message));
- msg->m.mn_Node.ln_Type = NT_MESSAGE;
- memcpy(msg->data,str,stringlen);
- msg->m.mn_Length = allocsize;
-
- if(async)
- {
- /* no reply, don't free msg */
- msg->m.mn_ReplyPort = NULL;
- PutMsg(mpo->port, &msg->m);
- }
- else
- {
- /* we should wait for a reply and then free the message */
- ULONG sigs;
- msg->m.mn_ReplyPort = mpo->replyPort;
- PutMsg(mpo->port,&msg->m);
- sigs = Wait((1<<msg->m.mn_ReplyPort->mp_SigBit) | SIGBREAKF_CTRL_C); /* XXX Abort with ^C */
- if(sigs & SIGBREAKF_CTRL_C)
- {
- PyErr_SetNone(PyExc_KeyboardInterrupt);
- return NULL;
- }
- (void)GetMsg(msg->m.mn_ReplyPort);
- FreeMem(msg,msg->m.mn_Length);
- }
- Py_INCREF(Py_None);
- return Py_None;
- }
- else return PyErr_NoMemory();
- }
- return NULL;
- }
-
- static struct PyMethodDef port_methods[] = {
- {"close", (PyCFunction)port_close, 0},
- {"wait", (PyCFunction)port_wait, 0},
- {"getmsg", (PyCFunction)port_getmsg, 1},
- {"putmsg", (PyCFunction)port_putmsg, 1},
- {NULL, NULL} /* sentinel */
- };
-
- static void
- port_dealloc(MsgPortobject *self) // `destructor'
- {
- if(!self->fromExisting) DeleteMsgPortSafely(self->port,0);
- DeleteMsgPortSafely(self->replyPort,1);
- PyMem_DEL(self);
- }
-
- static PyObject *
- port_getattr(MsgPortobject *mpo, char *name)
- {
- if(mpo->port)
- {
- if (strcmp(name, "name")==0)
- {
- if(!mpo->port->mp_Node.ln_Name)
- {
- // port has no name
- PyErr_SetString(PyExc_AttributeError,name); return NULL;
- }
- return PyString_FromString(mpo->port->mp_Node.ln_Name);
- }
- else if(strcmp(name,"signal")==0)
- return PyInt_FromLong(1<<mpo->port->mp_SigBit);
- }
- return Py_FindMethod(port_methods, (PyObject *)mpo, name);
- }
-
- static PyObject *
- port_repr(MsgPortobject *mpo)
- {
- char buf[200];
- char *w;
-
- if(!(mpo->port))
- w="(closed)";
- else if(!mpo->port->mp_Node.ln_Name)
- w="(private)";
- else
- w=mpo->port->mp_Node.ln_Name;
- sprintf(buf,"<MsgPort %s at %lx>",w,(long)mpo);
- return PyString_FromString(buf);
- }
-
- static PyTypeObject MsgPortType = {
- PyObject_HEAD_INIT(&PyType_Type)
- 0, /*ob_size*/
- "MsgPort", /*tp_name*/
- sizeof(MsgPortobject), /*tp_size*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)port_dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)port_getattr, /*tp_getattr*/
- (setattrfunc)0, /*tp_setattr*/
- 0, /*tp_compare*/
- (reprfunc)port_repr, /*tp_repr*/
- };
-
-
- ///
-
-
- ///******************************** MODULE FUNCTIONS ************************/
-
- static PyObject *
- amiga_exec_FindPort(PyObject *self, PyObject *args)
- {
- char *name;
- struct MsgPort *port;
-
- if (!PyArg_ParseTuple(args, "s", &name))
- return NULL;
-
- if(port=FindPort(name))
- {
- MsgPortobject *mpo;
- if(mpo = PyObject_NEW(MsgPortobject, &MsgPortType))
- {
- mpo->port = port;
- mpo->fromExisting = 1;
- if(mpo->replyPort = CreateMsgPort())
- {
- return (PyObject*) mpo;
- }
- /* could not create replyport */
- Py_DECREF(mpo);
- return PyErr_NoMemory();
- }
- else return NULL;
- }
- PyErr_SetString(error,"Can't find MsgPort");
- return NULL;
- }
-
- static PyObject *
- amiga_exec_listMsgPorts(PyObject *self, PyObject *args)
- {
- PyObject *list;
- PyObject *item;
-
- if (!PyArg_ParseTuple(args, "")) return NULL;
-
- if(list = PyList_New(0))
- {
- struct Node *node;
- int failed=0;
- Forbid();
- for (node = SysBase->PortList.lh_Head; node->ln_Succ; node = node->ln_Succ)
- {
- if(item = PyString_FromString(node->ln_Name))
- {
- if(PyList_Append(list,item)!=0)
- {
- Py_DECREF(item);
- failed=1; break;
- }
- }
- else
- {
- failed=1; break;
- }
- }
- Permit();
- if(failed)
- {
- Py_DECREF(list);
- return PyErr_NoMemory();
- }
- return list;
- }
- else return NULL;
- }
-
-
- static PyObject *
- amiga_exec_CreateMsgPort(PyObject *self, PyObject *args)
- {
- MsgPortobject *mpo;
- char *name;
-
- if (!PyArg_ParseTuple(args, "z", &name))
- return NULL;
-
- if(name)
- {
- if(strlen(name)>MAX_PORTNAME_LEN)
- {
- PyErr_SetString(error,"Portname too long");
- return NULL;
- }
- if(name[0]=='\0')
- {
- name=NULL;
- }
- }
-
- if(name && FindPort(name))
- {
- PyErr_SetString(error,"Port already exists with this name");
- return NULL;
- }
-
- if(mpo = PyObject_NEW(MsgPortobject, &MsgPortType))
- {
- mpo->fromExisting=0;
- if(mpo->port = CreateMsgPort())
- {
- if(name)
- {
- strcpy(mpo->name,name);
- mpo->port->mp_Node.ln_Name = &(mpo->name[0]);
- AddPort(mpo->port);
- }
-
- if(mpo->replyPort = CreateMsgPort())
- {
- /** all went OK! **/
- return (PyObject*) mpo;
- }
-
- /** something went wrong, clean up **/
- if(name)
- RemPort(mpo->port);
-
- DeleteMsgPortSafely(mpo->port,0);
- mpo->port=NULL;
- }
- PyErr_SetString(error,"can't open port");
-
- PyMem_DEL(mpo); mpo=NULL;
- }
- return (PyObject*)mpo;
- }
-
-
- /*** FUNCTIONS FROM THE MODULE ***/
-
- static struct PyMethodDef amiga_exec_global_methods[] = {
- {"CreateMsgPort", amiga_exec_CreateMsgPort, 1},
- {"FindPort", amiga_exec_FindPort, 1},
- {"list_MsgPorts", amiga_exec_listMsgPorts, 1},
- {NULL, NULL} /* sentinel */
- };
- ///
-
- void
- initamiga_exec Py_PROTO((void))
- {
- PyObject *m, *d;
-
- m = Py_InitModule("amiga_exec", amiga_exec_global_methods);
- d = PyModule_GetDict(m);
-
- /* Initialize error exception */
- error = PyErr_NewException("amiga_exec.error", NULL, NULL);
- if (error != NULL)
- PyDict_SetItemString(d, "error", error);
- }
-