chiark / gitweb /
@@@ mdwopt broken wip
[mLib-python] / sys.c
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
34 static 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;
45 end:
46   Py_XDECREF(t);
47   return (rc);
48 }
49
50 static 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;
62 end:
63   Py_XDECREF(t);
64   return (rc);
65 }
66
67 static PyObject *meth_detachtty(PyObject *me)
68   { detachtty(); RETURN_NONE; }
69
70 static PyObject *meth_daemonize(PyObject *me)
71 {
72   if (daemonize()) OSERR(0);
73   RETURN_NONE;
74 end:
75   return (0);
76 }
77
78 static 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;
92 end:
93   return (0);
94 }
95
96 static 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);
110 end:
111   return (rc);
112 }
113
114 static 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;
130 end:
131   Py_XDECREF(buf);
132   return (rc);
133 }
134
135 static 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
174 end:
175   Py_XDECREF(t); Py_XDECREF(u);
176   return (rc);
177 }
178
179 static 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
197 void sys_pyinit(void)
198 {
199   addmethods(methods);
200 }
201
202 void sys_pyinsert(PyObject *mod)
203 {
204 }
205
206 /*----- That's all, folks -------------------------------------------------*/