chiark / gitweb /
@@@ remove debugging print
[mLib-python] / sys.c
CommitLineData
81f68b64
MW
1/* -*-c-*-
2 *
3 * System-specific functionality
4 *
5 * (c) 2019 Straylight/Edgeware
6 */
7
8/*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of the Python interface to mLib.
11 *
12 * mLib/Python is free software: you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * mLib/Python is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with mLib/Python. If not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
25 * USA.
26 */
27
28/*----- Header files ------------------------------------------------------*/
29
30#include "mLib-python.h"
31
32/*----- Main code ---------------------------------------------------------*/
33
34static int getint(PyObject *obj, int *i_out)
35{
36 PyObject *t = 0;
37 long i;
38 int rc = -1;
39
40 t = PyNumber_Index(obj); if (!t) goto end;
41 i = PyInt_AsLong(t); if (i == -1 && PyErr_Occurred()) goto end;
42 if (INT_MIN > i || i > INT_MAX) OVFERR("out of range");
43 *i_out = i;
44 rc = 0;
45end:
46 Py_XDECREF(t);
47 return (rc);
48}
49
50static int convfd(PyObject *obj, void *p)
51{
52 int *fd_out = p;
53 PyObject *t = 0;
54 int rc = 0;
55
56 if (getint(obj, fd_out)) {
57 PyErr_Clear();
58 t = PyObject_CallMethod(obj, "fileno", 0); if (!t) goto end;
59 if (getint(t, fd_out)) goto end;
60 }
61 rc = 1;
62end:
63 Py_XDECREF(t);
64 return (rc);
65}
66
67static PyObject *meth_detachtty(PyObject *me)
68 { detachtty(); RETURN_NONE; }
69
70static PyObject *meth_daemonize(PyObject *me)
71{
72 if (daemonize()) OSERR(0);
73 RETURN_NONE;
74end:
75 return (0);
76}
77
78static PyObject *meth_fdflags(PyObject *me, PyObject *arg, PyObject *kw)
79{
80 int fd;
81 unsigned fbic = 0, fxor = 0, fdbic = 0, fdxor = 0;
82 static const char *const kwlist[] =
83 { "file", "fbic", "fxor", "fdbic", "fdxor", 0 };
84
85 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&|O&O&O&O&:fdflags", KWLIST,
86 convfd, &fd,
87 convuint, &fbic, convuint, &fxor,
88 convuint, &fdbic, convuint, &fdxor))
89 goto end;
90 if (fdflags(fd, fbic, fxor, fdbic, fdxor)) OSERR(0);
91 RETURN_NONE;
92end:
93 return (0);
94}
95
96static PyObject *meth_fdsend(PyObject *me, PyObject *arg, PyObject *kw)
97{
98 int sock, fd;
99 struct bin buf;
100 ssize_t n;
101 PyObject *rc = 0;
102 static const char *const kwlist[] = { "sock", "file", "buffer", 0 };
103
104 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&O&:fdsend", KWLIST,
105 convfd, &sock, convfd, &fd,
106 convbin, &buf))
107 goto end;
108 n = fdpass_send(sock, fd, buf.p, buf.sz); if (n < 0) OSERR(0);
109 rc = PyInt_FromLong(n);
110end:
111 return (rc);
112}
113
114static PyObject *meth_fdrecv(PyObject *me, PyObject *arg, PyObject *kw)
115{
116 int sock, fd;
117 size_t sz;
118 ssize_t n;
119 void *p;
120 PyObject *buf = 0, *rc = 0;
121 static const char *const kwlist[] = { "sock", "size", 0 };
122
123 if (!PyArg_ParseTupleAndKeywords(arg, kw, "O&O&:fdrecv", KWLIST,
124 convfd, &sock, convszt, &sz))
125 goto end;
126 BIN_PREPAREWRITE(buf, p, sz);
127 n = fdpass_recv(sock, &fd, p, sz); if (n < 0) OSERR(0);
128 BIN_DONEWRITE(buf, n);
129 rc = Py_BuildValue("(iN)", fd, buf); buf = 0;
130end:
131 Py_XDECREF(buf);
132 return (rc);
133}
134
135static PyObject *meth_mdup(PyObject *me, PyObject *arg)
136{
137 PyObject *v;
138 PyObject *t = 0, *u = 0, *rc = 0;
139 Py_ssize_t n, m;
140 mdup_fd *vv;
141 size_t i;
142 int err;
143
144 if (!PyArg_ParseTuple(arg, "O:mdup", &v)) goto end;
145 n = PySequence_Size(v); if (n < 0) goto end;
146 vv = xmalloc(n*sizeof(*vv));
147 for (i = 0; i < n; i++) {
148 t = PySequence_GetItem(v, i); if (!t) goto end;
149 m = PySequence_Size(t); if (m < 0) goto end;
150 if (m != 2) VALERR("expected a list of pairs");
151
152 u = PySequence_GetItem(t, 0);
153 if (getint(u, &vv[i].cur)) goto end;
154 Py_DECREF(u); u = 0;
155
156 u = PySequence_GetItem(t, 1);
157 if (getint(u, &vv[i].want)) goto end;
158 Py_DECREF(u); u = 0;
159
160 Py_DECREF(t); t = 0;
161 }
162
163 err = mdup(vv, n);
164
165 for (i = 0; i < n; i++) {
166 t = Py_BuildValue("(ii)", vv[i].cur, vv[i].want);
167 if (PySequence_SetItem(v, i, t)) goto end;
168 Py_DECREF(t); t = 0;
169 }
170
171 if (err) OSERR(0);
172 rc = v; Py_INCREF(rc);
173
174end:
175 Py_XDECREF(t); Py_XDECREF(u);
176 return (rc);
177}
178
179static const PyMethodDef methods[] = {
180#define METHNAME(name) meth_##name
181 NAMETH(detachtty, "detachtty(): fork, detatch controlling terminal")
182 NAMETH(daemonize, "daemonize(): fork and become a daemon")
183 KWMETH(fdflags, "fdflags(FILE, [fbic = 0], [fxor = 0], "
184 "[fdbic = 0], [fdxor = 0])")
185 KWMETH(fdsend, "fdsend(FILE, FD, BUFFER) -> N")
186 KWMETH(fdrecv, "fdrecv(FILE, SIZE) -> FD, BUFFER")
187 METH (mdup, "mdup(LIST) -> LIST:\n"
188 " LIST is a list (mutable sequence) of pairs (CUR, WANT). Duplicate\n"
189 " each CUR file descriptor as WANT (may be -1 to mean `don't care'),\n"
190 " closing original CUR. Works even if there are cycles. LIST is\n"
191 " updated in place with CUR reflecting the new file descriptors even\n"
192 " on error. Returns the same LIST on success.")
193#undef METHNAME
194 { 0 }
195};
196
197void sys_pyinit(void)
198{
199 addmethods(methods);
200}
201
202void sys_pyinsert(PyObject *mod)
203{
204}
205
206/*----- That's all, folks -------------------------------------------------*/