source: protocols/python/src/bpython.c @ 26f3b5f

Last change on this file since 26f3b5f was 26f3b5f, checked in by Nick Murdoch <nick@…>, at 2013-03-19T19:58:17Z

Create a shell Protocol class for the module.

Can't currently do much with it, including even subclassing.

  • Property mode set to 100644
File size: 5.9 KB
Line 
1/*
2 * bpython.c - Python plugin for bitlbee
3 *
4 * Copyright (c) 2013 Nick Murdoch
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <bitlbee.h>
26#include <Python.h>
27#include "bytesobject.h"
28
29/* Python module classes: */
30
31typedef struct {
32    PyObject_HEAD
33
34} bpython_ProtocolObject;
35
36static PyTypeObject bpython_ProtocolType = {
37    PyObject_HEAD_INIT(NULL)
38    0,                         /*ob_size*/
39    "bpython.Protocol",  /*tp_name*/
40    sizeof(bpython_ProtocolObject), /*tp_basicsize*/
41    0,                         /*tp_itemsize*/
42    0,                         /*tp_dealloc*/
43    0,                         /*tp_print*/
44    0,                         /*tp_getattr*/
45    0,                         /*tp_setattr*/
46    0,                         /*tp_compare*/
47    0,                         /*tp_repr*/
48    0,                         /*tp_as_number*/
49    0,                         /*tp_as_sequence*/
50    0,                         /*tp_as_mapping*/
51    0,                         /*tp_hash */
52    0,                         /*tp_call*/
53    0,                         /*tp_str*/
54    0,                         /*tp_getattro*/
55    0,                         /*tp_setattro*/
56    0,                         /*tp_as_buffer*/
57    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
58    "Protocol plugin objects",           /* tp_doc */
59};
60
61/* Python module functions: */
62
63static PyObject * bpython_register_protocol(PyObject *self, PyObject *args)
64{
65    const char *command;
66    int sts;
67
68    if (!PyArg_ParseTuple(args, "s", &command))
69        return NULL;
70    sts = system(command);
71    return Py_BuildValue("i", sts);
72}
73
74static PyMethodDef BpythonMethods[] = {
75    {"register_protocol",  bpython_register_protocol, METH_VARARGS,
76     "Register a protocol."},
77    {NULL, NULL, 0, NULL}        /* Sentinel */
78};
79
80PyMODINIT_FUNC initbpython(void)
81{
82    PyObject * m;
83
84    bpython_ProtocolType.tp_new = PyType_GenericNew;
85    if (PyType_Ready(&bpython_ProtocolType) < 0) {
86        return;
87    }
88
89    m = Py_InitModule3("bpython", BpythonMethods, "Bitlbee Plugin module");
90
91    Py_INCREF(&bpython_ProtocolType);
92    PyModule_AddObject(m, "Protocol", (PyObject *)&bpython_ProtocolType);
93}
94
95
96static void load_pyfile(char * path, PyObject * main_dict) {
97    PyObject * err;
98    struct prpl *ret;
99    ret = g_new0(struct prpl, 1);
100   
101    PyObject * pluginname = PyDict_GetItemString(main_dict, "name");
102    if ((err = PyErr_Occurred()) || !pluginname) {
103        printf("No plugin name\n");
104        PyErr_Print();
105        g_free(ret);
106        return;
107    }
108    PyObject * pluginname_unicode = PyObject_Unicode(pluginname);
109    PyObject * pluginname_encoded = PyUnicode_AsEncodedString(pluginname_unicode, "ascii", "ignore");
110    if ((err = PyErr_Occurred())) {
111        printf("Error encoding plugin name\n");
112        PyErr_Print();
113        g_free(ret);
114        return;
115    }
116    char * pluginname_tmp; /* reference, do not modify */
117    Py_ssize_t length;
118    PyBytes_AsStringAndSize(pluginname_encoded, &pluginname_tmp, &length);
119    if ((err = PyErr_Occurred())) {
120        printf("Bad plugin name\n");
121        PyErr_Print();
122        g_free(ret);
123        return;
124    }
125    ret->name = g_malloc0(length + 1);
126    memmove(ret->name, pluginname_tmp, length);
127
128    Py_DECREF(pluginname_encoded);
129    Py_DECREF(pluginname_unicode);
130
131    register_protocol(ret);
132}
133
134/* Bitlbee plugin functions: */
135
136void init_plugin() {
137    GDir *dir;
138    GError *error = NULL;
139
140    printf("Initialising Python... ");
141    Py_Initialize();
142    PyRun_SimpleString("print 'Python initialised!'\n");
143   
144    /* Add our static module */
145    initbpython();
146
147    /* Get a reference to the main module. */
148    PyObject* main_module = PyImport_AddModule("__main__");
149
150    /* Get the main module's dictionary */
151    PyObject* main_dict = PyModule_GetDict(main_module);
152
153    dir = g_dir_open(global.conf->plugindir, 0, &error);
154    if (dir) {
155        const gchar *entry;
156        char * path;
157        while ((entry = g_dir_read_name(dir))) {
158            path = g_build_filename(global.conf->plugindir, entry, NULL);
159            if (!path) {
160                log_message(LOGLVL_WARNING, "Can't build path for %s\n", entry);
161                continue;
162            }
163           
164            if (g_str_has_suffix(path, ".py")) {
165                FILE * pyfile;
166                printf("Loading python file %s\n", path);
167                pyfile = fopen(path, "r");
168               
169                /* Copy main dict to make sure that separate plugins
170                   run in separate environments */
171                PyObject * main_dict_copy = PyDict_Copy(main_dict);
172
173                /* Run the python file */
174                PyRun_File(pyfile, path, Py_file_input, main_dict_copy, main_dict_copy);
175
176            }
177
178            g_free(path);
179        }
180    }
181
182    // Py_Finalize(); // TODO - there's no plugin_unload for us to do this in.
183}
184
185int main(int argc, char ** argv) {
186    printf("This is a bitlbee plugin, you should place it in bitlbee's plugins directory.");
187    return 0;
188}
Note: See TracBrowser for help on using the repository browser.