rpm  5.4.10
rpmpython.c
Go to the documentation of this file.
1 #include "system.h"
2 
3 #define _RPMIOB_INTERNAL /* XXX necessary? */
4 #include <rpmiotypes.h>
5 #include <rpmmacro.h>
6 #include <argv.h>
7 
8 #define _RPMPYTHON_INTERNAL
9 #include "rpmpython.h"
10 
11 #if defined(MODULE_EMBED)
12 #include <Python.h>
13 #include <cStringIO.h>
14 #undef WITH_PYTHONEMBED
15 #endif
16 
17 #if defined(WITH_PYTHONEMBED)
18 #include <dlfcn.h>
19 #include <rpmlog.h>
20 #endif
21 
22 #include "debug.h"
23 
24 /*@unchecked@*/
26 
27 /*@unchecked@*/ /*@relnull@*/
29 
30 #if defined(WITH_PYTHONEMBED)
31 static int dlopened = 0;
32 static rpmpython (*rpmpythonNew_p) (char ** av, uint32_t flags);
33 static rpmRC (*rpmpythonRunFile_p) (rpmpython python, const char * fn, const char ** resultp);
34 static rpmRC (*rpmpythonRun_p) (rpmpython python, const char * str, const char ** resultp);
35 #endif
36 
37 static void rpmpythonFini(void * _python)
38  /*@globals fileSystem @*/
39  /*@modifies *_python, fileSystem @*/
40 {
41  rpmpython python = (rpmpython) _python;
42 
43 #if defined(MODULE_EMBED)
44  Py_Finalize();
45 #endif
46  python->I = NULL;
47 }
48 
49 /*@unchecked@*/ /*@only@*/ /*@null@*/
51 
52 static rpmpython rpmpythonGetPool(/*@null@*/ rpmioPool pool)
53  /*@globals _rpmpythonPool, fileSystem @*/
54  /*@modifies pool, _rpmpythonPool, fileSystem @*/
55 {
56  rpmpython python;
57 
58  if (_rpmpythonPool == NULL) {
59  _rpmpythonPool = rpmioNewPool("python", sizeof(*python), -1, _rpmpython_debug,
60  NULL, NULL, rpmpythonFini);
61  pool = _rpmpythonPool;
62  }
63  return (rpmpython) rpmioGetPool(pool, sizeof(*python));
64 }
65 
66 /*@unchecked@*/
67 #if defined(MODULE_EMBED)
68 static const char * _rpmpythonI_init = "\
69 import sys\n\
70 from cStringIO import StringIO\n\
71 sys.stdout = StringIO()\n\
72 ";
73 #endif
74 
75 static rpmpython rpmpythonI(void)
76  /*@globals _rpmpythonI @*/
77  /*@modifies _rpmpythonI @*/
78 {
79  if (_rpmpythonI == NULL)
80  _rpmpythonI = rpmpythonNew(NULL, 0);
81  return _rpmpythonI;
82 }
83 
84 #if defined(WITH_PYTHONEMBED)
85 static void loadModule(void) {
86  const char librpmpython[] = "rpmpython.so";
87  void *h;
88 
89  h = dlopen (librpmpython, RTLD_NOW|RTLD_GLOBAL);
90  if (!h)
91  {
92  rpmlog(RPMLOG_WARNING, D_("Unable to open \"%s\" (%s), "
93  "embedded python will not be available\n"),
94  librpmpython, dlerror());
95  }
96  else if(!((rpmpythonNew_p = dlsym(h, "rpmpythonNew"))
97  && (rpmpythonRunFile_p = dlsym(h, "rpmpythonRunFile"))
98  && (rpmpythonRun_p = dlsym(h, "rpmpythonRun")))) {
99  rpmlog(RPMLOG_WARNING, D_("Opened library \"%s\" is incompatible (%s), "
100  "embedded python will not be available\n"),
101  librpmpython, dlerror());
102  if (dlclose (h))
103  rpmlog(RPMLOG_WARNING, "Error closing library \"%s\": %s", librpmpython,
104  dlerror());
105  } else
106  dlopened = 1;
107 }
108 #endif
109 
110 rpmpython rpmpythonNew(char ** av, uint32_t flags)
111 {
112 #if defined(WITH_PYTHONEMBED)
113  if (!dlopened) loadModule();
114  if (dlopened) return rpmpythonNew_p(av, flags);
115 #endif
116  static char * _av[] = { "rpmpython", NULL };
117 #if defined(MODULE_EMBED)
118  int initialize = (!(flags & 0x80000000) || _rpmpythonI == NULL);
119 #endif
120  rpmpython python = (flags & 0x80000000)
121  ? rpmpythonI() : rpmpythonGetPool(_rpmpythonPool);
122 
123 if (_rpmpython_debug)
124 fprintf(stderr, "==> %s(%p, %d) python %p\n", __FUNCTION__, av, flags, python);
125 
126  if (av == NULL) av = _av;
127 
128 #if defined(MODULE_EMBED)
129  if (!Py_IsInitialized()) {
130  Py_SetProgramName((char *)_av[0]);
131  Py_Initialize();
132  }
133  if (PycStringIO == NULL)
134  PycStringIO = (struct PycStringIO_CAPI *)
135  PyCObject_Import("cStringIO", "cStringIO_CAPI");
136 
137  if (initialize) {
138  static const char _pythonI_init[] = "%{?_pythonI_init}";
139  const char * s = rpmExpand(_rpmpythonI_init, _pythonI_init, NULL);
140  int ac = argvCount((ARGV_t)av);
141  (void) PySys_SetArgv(ac, (char **)av);
142 fprintf(stderr, "==========\n%s\n==========\n", s);
143  (void) rpmpythonRun(python, s, NULL);
144  s = _free(s);
145  }
146 #endif
147 
148  return rpmpythonLink(python);
149 }
150 
151 rpmRC rpmpythonRunFile(rpmpython python, const char * fn, const char ** resultp)
152 {
153 #if defined(WITH_PYTHONEMBED)
154  if (dlopened) return rpmpythonRunFile_p(python, fn, resultp);
155 #endif
156  rpmRC rc = RPMRC_FAIL;
157 
158 if (_rpmpython_debug)
159 fprintf(stderr, "==> %s(%p,%s)\n", __FUNCTION__, python, fn);
160 
161  if (python == NULL) python = rpmpythonI();
162 
163  if (fn != NULL) {
164 #if defined(MODULE_EMBED)
165  const char * pyfn = ((fn == NULL || !strcmp(fn, "-")) ? "<stdin>" : fn);
166  FILE * pyfp = (!strcmp(pyfn, "<stdin>") ? stdin : fopen(fn, "rb"));
167  int closeit = (pyfp != stdin);
168  PyCompilerFlags cf = { 0 };
169 
170  if (pyfp != NULL) {
171  PyRun_AnyFileExFlags(pyfp, pyfn, closeit, &cf);
172  rc = RPMRC_OK;
173  }
174 #endif
175  }
176  return rc;
177 }
178 
179 static const char * rpmpythonSlurp(const char * arg)
180  /*@*/
181 {
182  rpmiob iob = NULL;
183  const char * val = NULL;
184  struct stat sb;
185  int xx;
186 
187  if (!strcmp(arg, "-")) { /* Macros from stdin arg. */
188  xx = rpmiobSlurp(arg, &iob);
189  } else
190  if ((arg[0] == '/' || strchr(arg, ' ') == NULL)
191  && !Stat(arg, &sb)
192  && S_ISREG(sb.st_mode)) { /* Macros from a file arg. */
193  xx = rpmiobSlurp(arg, &iob);
194  } else { /* Macros from string arg. */
195  iob = rpmiobAppend(rpmiobNew(strlen(arg)+1), arg, 0);
196  }
197 
198  val = xstrdup(rpmiobStr(iob));
199  iob = rpmiobFree(iob);
200  return val;
201 }
202 
203 rpmRC rpmpythonRun(rpmpython python, const char * str, const char ** resultp)
204 {
205 #if defined(WITH_PYTHONEMBED)
206  if (dlopened) return rpmpythonRun_p(python, str, resultp);
207 #endif
208  rpmRC rc = RPMRC_FAIL;
209 
210 if (_rpmpython_debug)
211 fprintf(stderr, "==> %s(%p,%s,%p)\n", __FUNCTION__, python, str, resultp);
212 
213  if (python == NULL) python = rpmpythonI();
214 
215  if (str != NULL) {
216  const char * val = rpmpythonSlurp(str);
217 #if defined(MODULE_EMBED)
218  PyCompilerFlags cf = { 0 };
219  PyObject * m = PyImport_AddModule("__main__");
220  PyObject * d = (m ? PyModule_GetDict(m) : NULL);
221  PyObject * v = (m ? PyRun_StringFlags(val, Py_single_input, d, d, &cf) : NULL);
222 
223  if (v == NULL) {
224  PyErr_Print();
225  } else {
226  if (resultp != NULL) {
227  PyObject * sys_stdout = PySys_GetObject((char *)"stdout");
228  if (sys_stdout != NULL && PycStringIO_OutputCheck(sys_stdout)) {
229  PyObject * o = (*PycStringIO->cgetvalue)(sys_stdout);
230  *resultp = (PyString_Check(o) ? PyString_AsString(o) : "");
231  } else
232  *resultp = "";
233  }
234  Py_XDECREF(v);
235  if (Py_FlushLine())
236  PyErr_Clear();
237  rc = RPMRC_OK;
238  }
239 #endif
240  val = _free(val);
241  }
242  return rc;
243 }
rpmioPool _rpmpythonPool
Definition: rpmpython.c:50
char * xstrdup(const char *str)
Definition: rpmmalloc.c:322
static rpmpython rpmpythonI(void)
Definition: rpmpython.c:75
int Stat(const char *path, struct stat *st)
stat(2) clone.
Definition: rpmrpc.c:1361
rpmRC rpmpythonRunFile(rpmpython python, const char *fn, const char **resultp)
Execute python from a file.
Definition: rpmpython.c:151
rpmiob rpmiobFree(rpmiob iob)
Destroy a I/O buffer instance.
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
rpmiob rpmiobAppend(rpmiob iob, const char *s, size_t nl)
Append string to I/O buffer.
Definition: rpmiob.c:78
rpmpython _rpmpythonI
Definition: rpmpython.c:28
int rpmiobSlurp(const char *fn, rpmiob *iobp)
Definition: rpmiob.c:130
static void rpmpythonFini(void *_python)
Definition: rpmpython.c:37
Yet Another syslog(3) API clone.
static rpmpython rpmpythonGetPool(rpmioPool pool)
Definition: rpmpython.c:52
static const char * rpmpythonSlurp(const char *arg)
Definition: rpmpython.c:179
rpmioItem rpmioGetPool(rpmioPool pool, size_t size)
Get unused item from pool, or alloc a new item.
Definition: rpmmalloc.c:221
rpmRC rpmpythonRun(rpmpython python, const char *str, const char **resultp)
Execute python string.
Definition: rpmpython.c:203
int argvCount(const ARGV_t argv)
Return no.
Definition: argv.c:71
struct rpmpython_s * rpmpython
Definition: rpmpython.h:11
rpmpython rpmpythonNew(char **av, uint32_t flags)
Create and load a python interpreter.
Definition: rpmpython.c:110
int _rpmpython_debug
Definition: rpmpython.c:25
char * rpmExpand(const char *arg,...)
Return (malloc&#39;ed) concatenated macro expansion(s).
Definition: macro.c:3117
rpmiob rpmiobNew(size_t len)
Create an I/O buffer.
Definition: rpmiob.c:44
enum rpmRC_e rpmRC
RPM return codes.
char * rpmiobStr(rpmiob iob)
Return I/O buffer (as string).
Definition: rpmiob.c:113
rpmioPool rpmioNewPool(const char *name, size_t size, int limit, int flags, char *(*dbg)(void *item), void(*init)(void *item), void(*fini)(void *item))
Create a memory pool.
Definition: rpmmalloc.c:110
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:647
struct rpmiob_s * rpmiob
Definition: rpmiotypes.h:57
ARGstr_t * ARGV_t
Definition: argv.h:9
#define D_(Text)
Definition: system.h:485
rpmpython rpmpythonLink(rpmpython python)
Reference a python interpreter instance.