Commit | Line | Data |
---|---|---|
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 | ||
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 -------------------------------------------------*/ |