chiark / gitweb /
catacomb/pwsafe.py: Use `binascii' for Base64 conversion.
[catacomb-python] / catacomb.c
1 /* -*-c-*-
2  *
3  * Where the fun begins
4  *
5  * (c) 2004 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of the Python interface to Catacomb.
11  *
12  * Catacomb/Python is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * Catacomb/Python is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Catacomb/Python; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "catacomb-python.h"
30
31 /*----- Main code ---------------------------------------------------------*/
32
33 PyObject *mexp_common(PyObject *me, PyObject *arg,
34                       size_t efsz,
35                       PyObject *(*id)(PyObject *),
36                       int (*fill)(void *, PyObject *,
37                                   PyObject *, PyObject *),
38                       PyObject *(*exp)(PyObject *, void *, int),
39                       void (*drop)(void *))
40 {
41   int i = 0, j, n, flat;
42   PyObject *qq, *x, *y, *z = 0;
43   char *v = 0, *vv;
44
45   if (PyTuple_GET_SIZE(arg) == 1)
46     arg = PyTuple_GET_ITEM(arg, 0);
47   Py_INCREF(arg);
48   if (!PySequence_Check(arg)) TYERR("not a sequence");
49   n = PySequence_Size(arg); if (n < 0) goto end;
50   if (!n) { z = id(me); goto end; }
51   x = PySequence_GetItem(arg, 0);
52   if (PySequence_Check(x))
53     flat = 0;
54   else {
55     if (n % 2) VALERR("must have even number of arguments");
56     n /= 2;
57     flat = 1;
58   }
59   Py_DECREF(x);
60
61   v = xmalloc(n * efsz);
62   for (i = j = 0, vv = v; i < n; i++, vv += efsz) {
63     if (flat) {
64       x = PySequence_GetItem(arg, j++);
65       y = PySequence_GetItem(arg, j++);
66     } else {
67       qq = PySequence_GetItem(arg, j++);
68       if (!qq) goto end;
69       if (!PySequence_Check(qq) || PySequence_Size(qq) != 2) {
70         Py_DECREF(qq);
71         TYERR("want a sequence of pairs");
72       }
73       x = PySequence_GetItem(qq, 0);
74       y = PySequence_GetItem(qq, 1);
75       Py_DECREF(qq);
76     }
77     if (!x || !y) goto end;
78     if (fill(vv, me, x, y)) {
79       Py_DECREF(x);
80       Py_DECREF(y);
81       if (!PyErr_Occurred())
82         PyErr_SetString(PyExc_TypeError, "type mismatch");
83       goto end;
84     }
85     Py_DECREF(x);
86     Py_DECREF(y);
87   }
88   z = exp(me, v, n);
89
90 end:
91   if (v) {
92     for (j = 0, vv = v; j < i; j++, vv += efsz)
93       drop(vv);
94     xfree(v);
95   }
96   Py_DECREF(arg);
97   return (z);
98 }
99
100 int convmpw(PyObject *o, void *pp)
101 {
102   unsigned long u;
103   unsigned *p = pp;
104
105   if (!convulong(o, &u)) goto end;
106   if (u > MPW_MAX) VALERR("out of range");
107   *p = u;
108   return (1);
109 end:
110   return (0);
111 }
112
113 static PyTypeObject *thingtab_pytype;
114
115 typedef struct thingentry {
116   sym_base _b;
117   PyObject *val;
118 } thingentry;
119 #define THING_VAL(x) (((thingentry *)(x))->val)
120
121 typedef struct thingtab_pyobj {
122   GMAP_PYOBJ_HEAD
123   sym_table t;
124 } thingtab_pyobj;
125 #define THINGTAB_T(x) (&((thingtab_pyobj *)(x))->t)
126
127 static void *thingtab_gmlookup(PyObject *me, PyObject *key, unsigned *f)
128 {
129   const char *p;
130
131   p = TEXT_STR(key); if (!p) return (0);
132   return (sym_find(THINGTAB_T(me), p, -1, 0, f));
133 }
134
135 static void thingtab_gmiterinit(PyObject *me, void *i)
136   { sym_mkiter(i, THINGTAB_T(me)); }
137
138 static void *thingtab_gmiternext(PyObject *me, void *i)
139   { sym_iter *it = i; void *e; SYM_NEXT(it, e); return (e); }
140
141 static PyObject *thingtab_gmentrykey(PyObject *me, void *e)
142   { return (TEXT_FROMSTR(SYM_NAME(e))); }
143
144 static PyObject *thingtab_gmentryvalue(PyObject *me, void *e)
145   { PyObject *rc = THING_VAL(e); RETURN_OBJ(rc); }
146
147 static const gmap_ops thingtab_gmops = {
148   sizeof(sym_iter),
149   thingtab_gmlookup,
150   thingtab_gmiterinit,
151   thingtab_gmiternext,
152   thingtab_gmentrykey,
153   thingtab_gmentryvalue
154 };
155
156 static Py_ssize_t thing_pysize(PyObject *me)
157   { return gmap_pysize_from_sym(THINGTAB_T(me)); }
158
159 static const PyMappingMethods thingtab_pymapping = {
160   thing_pysize,
161   gmap_pylookup,
162   0
163 };
164
165 static thingtab_pyobj *make_thingtab(void)
166 {
167   thingtab_pyobj *map = PyObject_NEW(thingtab_pyobj, thingtab_pytype);
168
169   map->gmops = &thingtab_gmops;
170   sym_create(&map->t);
171   return (map);
172 }
173
174 PyObject *make_algtab(const void *tab, size_t esz,
175                       const char *(*namefn)(const void *),
176                       PyObject *(*valfn)(const void *))
177 {
178   thingtab_pyobj *map = make_thingtab();
179   const char *p = tab;
180   const char *name;
181   thingentry *e;
182   unsigned f;
183
184   for (;;) {
185     name = namefn(p); if (!name) break;
186     e = sym_find(&map->t, name, -1, sizeof(*e), &f); assert(!f);
187     e->val = valfn(p);
188     p += esz;
189   }
190   return ((PyObject *)map);
191 }
192
193 PyObject *make_grouptab(const void *tab, size_t esz,
194                         const char *(*namefn)(const void *),
195                         int (*ixfn)(const void *), PyObject *(*valfn)(int))
196 {
197   thingtab_pyobj *map = make_thingtab();
198   struct { const char *name; int ix; } *ixtab = 0;
199   PyObject **valtab, **vv;
200   size_t i = 0, n = 0;
201   const char *p = tab;
202   const char *name;
203   thingentry *e;
204   unsigned f;
205
206   for (;;) {
207     name = namefn(p); if (!name) break;
208     if (i >= n) {
209       if (!n) n = 16;
210       else n *= 2;
211       ixtab = xrealloc(ixtab, n*sizeof(*ixtab), i*sizeof(*ixtab));
212     }
213     ixtab[i].name = name; ixtab[i].ix = ixfn(p); assert(ixtab[i].ix >= 0);
214     p += esz; i++;
215   }
216   n = i;
217
218   valtab = xmalloc(n*sizeof(*valtab));
219   for (i = 0; i < n; i++) valtab[i] = 0;
220
221   for (i = 0; i < n; i++) {
222     e = sym_find(&map->t, ixtab[i].name, -1, sizeof(*e), &f); assert(!f);
223     vv = &valtab[ixtab[i].ix];
224     if (*vv) Py_INCREF(*vv);
225     else *vv = valfn(ixtab[i].ix);
226     e->val = *vv;
227   }
228
229   xfree(ixtab); xfree(valtab);
230   return ((PyObject *)map);
231 }
232
233 static const PyTypeObject thingtab_pytype_skel = {
234   PyVarObject_HEAD_INIT(0, 0)           /* Header */
235   "_MiscTable",                         /* @tp_name@ */
236   sizeof(thingtab_pyobj),               /* @tp_basicsize@ */
237   0,                                    /* @tp_itemsize@ */
238
239   0,                                    /* @tp_dealloc@ */
240   0,                                    /* @tp_print@ */
241   0,                                    /* @tp_getattr@ */
242   0,                                    /* @tp_setattr@ */
243   0,                                    /* @tp_compare@ */
244   0,                                    /* @tp_repr@ */
245   0,                                    /* @tp_as_number@ */
246   PYSEQUENCE(gmap),                     /* @tp_as_sequence@ */
247   PYMAPPING(thingtab),                  /* @tp_as_mapping@ */
248   0,                                    /* @tp_hash@ */
249   0,                                    /* @tp_call@ */
250   0,                                    /* @tp_str@ */
251   0,                                    /* @tp_getattro@ */
252   0,                                    /* @tp_setattro@ */
253   0,                                    /* @tp_as_buffer@ */
254   Py_TPFLAGS_DEFAULT |                  /* @tp_flags@ */
255     Py_TPFLAGS_BASETYPE,
256
257   /* @tp_doc@ */
258   "Class for tables of algorithms and abstract-group data.\n"
259   "  Not instantiable by users.",
260
261   0,                                    /* @tp_traverse@ */
262   0,                                    /* @tp_clear@ */
263   0,                                    /* @tp_richcompare@ */
264   0,                                    /* @tp_weaklistoffset@ */
265   gmap_pyiter,                          /* @tp_iter@ */
266   0,                                    /* @tp_iternext@ */
267   PYMETHODS(gmapro),                    /* @tp_methods@ */
268   0,                                    /* @tp_members@ */
269   0,                                    /* @tp_getset@ */
270   0,                                    /* @tp_base@ */
271   0,                                    /* @tp_dict@ */
272   0,                                    /* @tp_descr_get@ */
273   0,                                    /* @tp_descr_set@ */
274   0,                                    /* @tp_dictoffset@ */
275   0,                                    /* @tp_init@ */
276   PyType_GenericAlloc,                  /* @tp_alloc@ */
277   abstract_pynew,                       /* @tp_new@ */
278   0,                                    /* @tp_free@ */
279   0                                     /* @tp_is_gc@ */
280 };
281
282 static PyObject *smallprimes(void)
283 {
284   PyObject *v = PyList_New(NPRIME);
285   int i;
286
287   for (i = 0; i < NPRIME; i++)
288     PyList_SET_ITEM(v, i, PyInt_FromLong(primetab[i]));
289   return (v);
290 }
291
292 static PyObject *meth__ego(PyObject *me, PyObject *arg)
293 {
294   char *argv0;
295   if (!PyArg_ParseTuple(arg, "s:_ego", &argv0))
296     return (0);
297   if (STRCMP(QUIS, ==, "<UNNAMED>"))
298     ego(argv0);
299   RETURN_NONE;
300 }
301
302 static const PyMethodDef methods[] = {
303 #define METHNAME(func) meth_##func
304   METH  (_ego,          "_ego(ARGV0)")
305 #undef METHNAME
306   { 0 }
307 };
308
309 static void init_random(void)
310 {
311 #if PY_VERSION_HEX >= 0x02060000
312   char *seed;
313   uint32 r;
314
315   if (!Py_HashRandomizationFlag) return;
316   seed = getenv("PYTHONHASHSEED");
317   if (!seed || STRCMP(seed, ==, "random")) r = GR_WORD(&rand_global);
318   else r = strtoul(seed, 0, 0);
319   if (!r) r = 0xe011f220; /* zero doesn't work well */
320   unihash_setkey(&unihash_global, r);
321 #endif
322 }
323
324 EXPORT void init_base(void)
325 {
326   PyObject *mod;
327
328   modname = TEXT_FROMSTR("catacomb");
329   addmethods(methods);
330   INIT_MODULES;
331   INITTYPE(thingtab, root);
332   init_random();
333   mod = Py_InitModule("catacomb._base", donemethods());
334   INSERT_MODULES;
335   INSERT("_MiscTable", thingtab_pytype);
336   INSERT("smallprimes", smallprimes());
337 }
338
339 /*----- That's all, folks -------------------------------------------------*/