source: web/old/remctl-2.14/python/_remctlmodule.c @ f6f3e91

web
Last change on this file since f6f3e91 was f6f3e91, checked in by Jessica B. Hamrick <jhamrick@…>, 15 years ago

Preserve directory hierarchy (not sure what happened to it)

  • Property mode set to 100644
File size: 7.6 KB
Line 
1/*
2 * Low-level Python interface to remctl.
3 *
4 * A direct Python equivalent to the libremctl API.  Normally, Python scripts
5 * should not use this interface directly; instead, they should use the remctl
6 * Python wrapper around this class.
7 *
8 * Original implementation by Thomas L. Kula <kula@tproa.net>
9 * Copyright 2008 Thomas L. Kula <kula@tproa.net>
10 * Copyright 2008 Board of Trustees, Leland Stanford Jr. University
11 *
12 * Permission to use, copy, modify, and distribute this software and its
13 * documentation for any purpose and without fee is hereby granted, provided
14 * that the above copyright notice appear in all copies and that both that
15 * copyright notice and this permission notice appear in supporting
16 * documentation, and that the name of Thomas L. Kula not be used in
17 * advertising or publicity pertaining to distribution of the software without
18 * specific, written prior permission. Thomas L. Kula makes no representations
19 * about the suitability of this software for any purpose.  It is provided "as
20 * is" without express or implied warranty.
21 *
22 * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
23 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25 */
26
27#include <Python.h>
28
29#include <errno.h>
30#include <stdlib.h>
31#include <string.h>
32#include <sys/uio.h>
33#include <unistd.h>
34
35#include <remctl.h>
36
37/* The type of the argument to PyString_AsStringAndSize changed in 2.5. */
38#if PY_VERSION_HEX < 0x02050000 && !defined(PY_SSIZE_T_MIN)
39typedef int Py_ssize_t;
40# define PY_SSIZE_T_MAX INT_MAX
41# define PY_SSIZE_T_MIN INT_MIN
42#endif
43
44/* Silence GCC warnings. */
45PyMODINIT_FUNC init_remctl(void);
46
47/* Map the remctl_output type constants to strings. */
48const struct {
49    enum remctl_output_type type;
50    const char *name;
51} OUTPUT_TYPE[] = {
52    { REMCTL_OUT_OUTPUT, "output" },
53    { REMCTL_OUT_STATUS, "status" },
54    { REMCTL_OUT_ERROR,  "error"  },
55    { REMCTL_OUT_DONE,   "done"   },
56    { 0,                 NULL     }
57};
58
59static PyObject *
60py_remctl(PyObject *self, PyObject *args)
61{
62    struct remctl_result *rr;
63    char *host = NULL;
64    unsigned short port;
65    char *principal = NULL;
66    const char **command = NULL;
67    PyObject *list = NULL;
68    PyObject *tmp = NULL;
69    int length, i;
70    PyObject *result = NULL;
71
72    if (!PyArg_ParseTuple(args, "sHzO", &host, &port, &principal, &list))
73        return NULL;
74
75    /*
76     * The command is passed as a list object.  For the remctl API, we need to
77     * turn it into a NULL-terminated array of pointers.
78     */
79    length = PyList_Size(list);
80    command = malloc((length + 1) * sizeof(char *));
81    if (command == NULL) {
82        PyErr_NoMemory();
83        return NULL;
84    }
85    for (i = 0; i < length; i++) {
86        tmp = PyList_GetItem(list, i);
87        if (tmp == NULL)
88            goto end;
89        command[i] = PyString_AsString(tmp);
90        if (command[i] == NULL)
91            goto end;
92    }
93    command[i] = NULL;
94
95    rr = remctl(host, port, principal, command);
96    if (rr == NULL) {
97        PyErr_NoMemory();
98        return NULL;
99    }
100    result = Py_BuildValue("(ss#s#i)", rr->error,
101                           rr->stdout_buf, (int) rr->stdout_len,
102                           rr->stderr_buf, (int) rr->stderr_buf,
103                           rr->status);
104    remctl_result_free(rr);
105
106end:
107    if (command != NULL)
108        free(command);
109    return result;
110}
111
112
113/*
114 * Called when the Python object is destroyed.  Clean up the underlying
115 * libremctl object.
116 */
117static void
118remctl_destruct(void *r)
119{
120    remctl_close(r);
121}
122
123
124static PyObject *
125py_remctl_new(PyObject *self, PyObject *args)
126{
127    struct remctl *r;
128
129    r = remctl_new();
130    if (r == NULL) {
131        PyErr_NoMemory();
132        return NULL;
133    }
134    return PyCObject_FromVoidPtr(r, remctl_destruct);
135}
136
137
138static PyObject *
139py_remctl_open(PyObject *self, PyObject *args)
140{
141    PyObject *object = NULL;
142    char *host = NULL;
143    unsigned short port = 0;
144    char *principal = NULL;
145    struct remctl *r;
146    int status;
147
148    if (!PyArg_ParseTuple(args, "Os|Hz", &object, &host, &port, &principal))
149        return NULL;
150    r = PyCObject_AsVoidPtr(object);
151    status = remctl_open(r, host, port, principal);
152    return Py_BuildValue("i", status);
153}
154
155
156static PyObject *
157py_remctl_close(PyObject *self, PyObject *args)
158{
159    PyObject *object = NULL;
160    struct remctl *r;
161
162    if (!PyArg_ParseTuple(args, "O", &object))
163        return NULL;
164    r = PyCObject_AsVoidPtr(object);
165    remctl_close(r);
166    Py_INCREF(Py_None);
167    return Py_None;
168}
169
170
171static PyObject *
172py_remctl_error(PyObject *self, PyObject *args)
173{
174    PyObject *object = NULL;
175    struct remctl *r;
176
177    if (!PyArg_ParseTuple(args, "O", &object))
178        return NULL;
179    r = PyCObject_AsVoidPtr(object);
180    return Py_BuildValue("s", remctl_error(r));
181}
182
183
184static PyObject *
185py_remctl_commandv(PyObject *self, PyObject *args)
186{
187    PyObject *object = NULL;
188    PyObject *list = NULL;
189    struct remctl *r;
190    struct iovec *iov;
191    size_t count, i;
192    char *string;
193    Py_ssize_t length;
194    PyObject *element;
195    PyObject *result = NULL;
196
197    if (!PyArg_ParseTuple(args, "OO", &object, &list))
198        return NULL;
199    r = PyCObject_AsVoidPtr(object);
200
201    /*
202     * Convert the Python list into an array of struct iovecs, each of which
203     * pointing to the elements of the list.
204     */
205    count = PyList_Size(list);
206    iov = malloc(count * sizeof(struct iovec));
207    if (iov == NULL) {
208        PyErr_NoMemory();
209        return NULL;
210    }
211    for (i = 0; i < count; i++) {
212        element = PyList_GetItem(list, i);
213        if (element == NULL)
214            goto end;
215        if (PyString_AsStringAndSize(element, &string, &length) == -1)
216            goto end;
217        iov[i].iov_base = string;
218        iov[i].iov_len = length;
219    }
220
221    if (remctl_commandv(r, iov, count)) {
222        Py_INCREF(Py_True);
223        result = Py_True;
224    } else {
225        Py_INCREF(Py_False);
226        result = Py_False;
227    }
228
229end:
230    if (iov != NULL)
231        free(iov);
232    return result;
233}
234
235
236static PyObject *
237py_remctl_output(PyObject *self, PyObject *args)
238{
239    PyObject *object = NULL;
240    struct remctl *r;
241    struct remctl_output *output;
242    const char *type = "unknown";
243    size_t i;
244    PyObject *result;
245
246    if (!PyArg_ParseTuple(args, "O", &object))
247        return NULL;
248    r = PyCObject_AsVoidPtr(object);
249    output = remctl_output(r);
250    if (output == NULL) {
251        Py_INCREF(Py_False);
252        return Py_False;
253    }
254    for (i = 0; OUTPUT_TYPE[i].name != NULL; i++)
255        if (OUTPUT_TYPE[i].type == output->type) {
256            type = OUTPUT_TYPE[output->type].name;
257            break;
258        }
259    result = Py_BuildValue("ss#iii", type, output->data, output->length,
260                           output->stream, output->status, output->error);
261    return result;
262}
263
264
265static PyMethodDef methods[] = {
266    { "remctl",          py_remctl,          METH_VARARGS, NULL },
267    { "remctl_new",      py_remctl_new,      METH_VARARGS, NULL },
268    { "remctl_open",     py_remctl_open,     METH_VARARGS, NULL },
269    { "remctl_close",    py_remctl_close,    METH_VARARGS, NULL },
270    { "remctl_error",    py_remctl_error,    METH_VARARGS, NULL },
271    { "remctl_commandv", py_remctl_commandv, METH_VARARGS, NULL },
272    { "remctl_output",   py_remctl_output,   METH_VARARGS, NULL },
273    { NULL,              NULL,               0,            NULL },
274};
275
276
277PyMODINIT_FUNC
278init_remctl(void)
279{
280    PyObject *module, *dict, *tmp;
281
282    module = Py_InitModule("_remctl", methods);
283    dict = PyModule_GetDict(module);
284
285    tmp = PyString_FromString(VERSION);
286    PyDict_SetItemString(dict, "VERSION", tmp);
287    Py_DECREF(tmp);
288}
Note: See TracBrowser for help on using the repository browser.