sysmodule.c revision bb5c6f8529c89d2396a3e3c06cf575a130ff7a0e
1/***********************************************************
2Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
4
5                        All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
16
17While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
29
30******************************************************************/
31
32/* System module */
33
34/*
35Various bits of information used by the interpreter are collected in
36module 'sys'.
37Function member:
38- exit(sts): raise SystemExit
39Data members:
40- stdin, stdout, stderr: standard file objects
41- modules: the table of modules (dictionary)
42- path: module search path (list of strings)
43- argv: script arguments (list of strings)
44- ps1, ps2: optional primary and secondary prompts (strings)
45*/
46
47#include "Python.h"
48
49#include "osdefs.h"
50
51PyObject *_PySys_TraceFunc, *_PySys_ProfileFunc;
52int _PySys_CheckInterval = 10;
53
54#if HAVE_UNISTD_H
55#include <unistd.h>
56#endif
57
58static PyObject *sysdict;
59
60#ifdef MS_COREDLL
61extern void *PyWin_DLLhModule;
62#endif
63
64PyObject *
65PySys_GetObject(name)
66	char *name;
67{
68	return PyDict_GetItemString(sysdict, name);
69}
70
71FILE *
72PySys_GetFile(name, def)
73	char *name;
74	FILE *def;
75{
76	FILE *fp = NULL;
77	PyObject *v = PySys_GetObject(name);
78	if (v != NULL && PyFile_Check(v))
79		fp = PyFile_AsFile(v);
80	if (fp == NULL)
81		fp = def;
82	return fp;
83}
84
85int
86PySys_SetObject(name, v)
87	char *name;
88	PyObject *v;
89{
90	if (v == NULL) {
91		if (PyDict_GetItemString(sysdict, name) == NULL)
92			return 0;
93		else
94			return PyDict_DelItemString(sysdict, name);
95	}
96	else
97		return PyDict_SetItemString(sysdict, name, v);
98}
99
100static PyObject *
101sys_exit(self, args)
102	PyObject *self;
103	PyObject *args;
104{
105	/* Raise SystemExit so callers may catch it or clean up. */
106	PyErr_SetObject(PyExc_SystemExit, args);
107	return NULL;
108}
109
110static PyObject *
111sys_settrace(self, args)
112	PyObject *self;
113	PyObject *args;
114{
115	if (args == Py_None)
116		args = NULL;
117	else
118		Py_XINCREF(args);
119	Py_XDECREF(_PySys_TraceFunc);
120	_PySys_TraceFunc = args;
121	Py_INCREF(Py_None);
122	return Py_None;
123}
124
125static PyObject *
126sys_setprofile(self, args)
127	PyObject *self;
128	PyObject *args;
129{
130	if (args == Py_None)
131		args = NULL;
132	else
133		Py_XINCREF(args);
134	Py_XDECREF(_PySys_ProfileFunc);
135	_PySys_ProfileFunc = args;
136	Py_INCREF(Py_None);
137	return Py_None;
138}
139
140static PyObject *
141sys_setcheckinterval(self, args)
142	PyObject *self;
143	PyObject *args;
144{
145	if (!PyArg_ParseTuple(args, "i", &_PySys_CheckInterval))
146		return NULL;
147	Py_INCREF(Py_None);
148	return Py_None;
149}
150
151#ifdef USE_MALLOPT
152/* Link with -lmalloc (or -lmpc) on an SGI */
153#include <malloc.h>
154
155static PyObject *
156sys_mdebug(self, args)
157	PyObject *self;
158	PyObject *args;
159{
160	int flag;
161	if (!PyArg_Parse(args, "i", &flag))
162		return NULL;
163	mallopt(M_DEBUG, flag);
164	Py_INCREF(Py_None);
165	return Py_None;
166}
167#endif /* USE_MALLOPT */
168
169static PyObject *
170sys_getrefcount(self, args)
171	PyObject *self;
172	PyObject *args;
173{
174	PyObject *arg;
175	if (!PyArg_Parse(args, "O", &arg))
176		return NULL;
177	return PyInt_FromLong((long) arg->ob_refcnt);
178}
179
180#ifdef COUNT_ALLOCS
181static PyObject *
182sys_getcounts(self, args)
183	PyObject *self, *args;
184{
185	extern PyObject *get_counts Py_PROTO((void));
186
187	if (!PyArg_Parse(args, ""))
188		return NULL;
189	return get_counts();
190}
191#endif
192
193#ifdef Py_TRACE_REFS
194/* Defined in objects.c because it uses static globals if that file */
195extern PyObject *_Py_GetObjects Py_PROTO((PyObject *, PyObject *));
196#endif
197
198#ifdef DYNAMIC_EXECUTION_PROFILE
199/* Defined in ceval.c because it uses static globals if that file */
200extern PyObject *_Py_GetDXProfile Py_PROTO((PyObject *,  PyObject *));
201#endif
202
203static PyMethodDef sys_methods[] = {
204	/* Might as well keep this in alphabetic order */
205	{"exit",	sys_exit, 0},
206#ifdef COUNT_ALLOCS
207	{"getcounts",	sys_getcounts, 0},
208#endif
209#ifdef DYNAMIC_EXECUTION_PROFILE
210	{"getdxp",	_Py_GetDXProfile, 1},
211#endif
212#ifdef Py_TRACE_REFS
213	{"getobjects",	_Py_GetObjects, 1},
214#endif
215	{"getrefcount",	sys_getrefcount, 0},
216#ifdef USE_MALLOPT
217	{"mdebug",	sys_mdebug, 0},
218#endif
219	{"setcheckinterval",	sys_setcheckinterval, 1},
220	{"setprofile",	sys_setprofile, 0},
221	{"settrace",	sys_settrace, 0},
222	{NULL,		NULL}		/* sentinel */
223};
224
225static PyObject *sysin, *sysout, *syserr;
226
227static PyObject *
228list_builtin_module_names()
229{
230	PyObject *list = PyList_New(0);
231	int i;
232	if (list == NULL)
233		return NULL;
234	for (i = 0; _PyImport_Inittab[i].name != NULL; i++) {
235		PyObject *name = PyString_FromString(_PyImport_Inittab[i].name);
236		if (name == NULL)
237			break;
238		PyList_Append(list, name);
239		Py_DECREF(name);
240	}
241	if (PyList_Sort(list) != 0) {
242		Py_DECREF(list);
243		list = NULL;
244	}
245	if (list) {
246		PyObject *v = PyList_AsTuple(list);
247		Py_DECREF(list);
248		list = v;
249	}
250	return list;
251}
252
253void
254PySys_Init()
255{
256	extern long PyInt_GetMax Py_PROTO((void));
257	extern char *Py_GetVersion Py_PROTO((void));
258	extern char *Py_GetCopyright Py_PROTO((void));
259	extern char *Py_GetPlatform Py_PROTO((void));
260	extern char *Py_GetPrefix Py_PROTO((void));
261	extern char *Py_GetExecPrefix Py_PROTO((void));
262	extern int fclose Py_PROTO((FILE *));
263	PyObject *m = Py_InitModule("sys", sys_methods);
264	PyObject *v;
265	sysdict = PyModule_GetDict(m);
266	Py_INCREF(sysdict);
267	/* NB keep an extra ref to the std files to avoid closing them
268	   when the user deletes them */
269	sysin = PyFile_FromFile(stdin, "<stdin>", "r", fclose);
270	sysout = PyFile_FromFile(stdout, "<stdout>", "w", fclose);
271	syserr = PyFile_FromFile(stderr, "<stderr>", "w", fclose);
272	if (PyErr_Occurred())
273		Py_FatalError("can't initialize sys.std{in,out,err}");
274	PyDict_SetItemString(sysdict, "stdin", sysin);
275	PyDict_SetItemString(sysdict, "stdout", sysout);
276	PyDict_SetItemString(sysdict, "stderr", syserr);
277	PyDict_SetItemString(sysdict, "version",
278			     v = PyString_FromString(Py_GetVersion()));
279	Py_XDECREF(v);
280	PyDict_SetItemString(sysdict, "copyright",
281			     v = PyString_FromString(Py_GetCopyright()));
282	Py_XDECREF(v);
283	PyDict_SetItemString(sysdict, "platform",
284			     v = PyString_FromString(Py_GetPlatform()));
285	Py_XDECREF(v);
286	PyDict_SetItemString(sysdict, "prefix",
287			     v = PyString_FromString(Py_GetPrefix()));
288	Py_XDECREF(v);
289	PyDict_SetItemString(sysdict, "exec_prefix",
290		   v = PyString_FromString(Py_GetExecPrefix()));
291	Py_XDECREF(v);
292	PyDict_SetItemString(sysdict, "maxint",
293			     v = PyInt_FromLong(PyInt_GetMax()));
294	Py_XDECREF(v);
295	PyDict_SetItemString(sysdict, "modules", PyImport_GetModuleDict());
296	PyDict_SetItemString(sysdict, "builtin_module_names",
297		   v = list_builtin_module_names());
298	Py_XDECREF(v);
299#ifdef MS_COREDLL
300	PyDict_SetItemString(sysdict, "dllhandle",
301			     v = PyInt_FromLong((int)PyWin_DLLhModule));
302	Py_XDECREF(v);
303	PyDict_SetItemString(sysdict, "winver",
304			     v = PyString_FromString(MS_DLL_ID));
305	Py_XDECREF(v);
306#endif
307	if (PyErr_Occurred())
308		Py_FatalError("can't insert sys.* objects in sys dict");
309}
310
311static PyObject *
312makepathobject(path, delim)
313	char *path;
314	int delim;
315{
316	int i, n;
317	char *p;
318	PyObject *v, *w;
319
320	n = 1;
321	p = path;
322	while ((p = strchr(p, delim)) != NULL) {
323		n++;
324		p++;
325	}
326	v = PyList_New(n);
327	if (v == NULL)
328		return NULL;
329	for (i = 0; ; i++) {
330		p = strchr(path, delim);
331		if (p == NULL)
332			p = strchr(path, '\0'); /* End of string */
333		w = PyString_FromStringAndSize(path, (int) (p - path));
334		if (w == NULL) {
335			Py_DECREF(v);
336			return NULL;
337		}
338		PyList_SetItem(v, i, w);
339		if (*p == '\0')
340			break;
341		path = p+1;
342	}
343	return v;
344}
345
346void
347PySys_SetPath(path)
348	char *path;
349{
350	PyObject *v;
351	if ((v = makepathobject(path, DELIM)) == NULL)
352		Py_FatalError("can't create sys.path");
353	if (PySys_SetObject("path", v) != 0)
354		Py_FatalError("can't assign sys.path");
355	Py_DECREF(v);
356}
357
358static PyObject *
359makeargvobject(argc, argv)
360	int argc;
361	char **argv;
362{
363	PyObject *av;
364	if (argc <= 0 || argv == NULL) {
365		/* Ensure at least one (empty) argument is seen */
366		static char *empty_argv[1] = {""};
367		argv = empty_argv;
368		argc = 1;
369	}
370	av = PyList_New(argc);
371	if (av != NULL) {
372		int i;
373		for (i = 0; i < argc; i++) {
374			PyObject *v = PyString_FromString(argv[i]);
375			if (v == NULL) {
376				Py_DECREF(av);
377				av = NULL;
378				break;
379			}
380			PyList_SetItem(av, i, v);
381		}
382	}
383	return av;
384}
385
386void
387PySys_SetArgv(argc, argv)
388	int argc;
389	char **argv;
390{
391	PyObject *av = makeargvobject(argc, argv);
392	PyObject *path = PySys_GetObject("path");
393	if (av == NULL)
394		Py_FatalError("no mem for sys.argv");
395	if (PySys_SetObject("argv", av) != 0)
396		Py_FatalError("can't assign sys.argv");
397	if (path != NULL) {
398		char *argv0 = argv[0];
399		char *p = NULL;
400		int n = 0;
401		PyObject *a;
402#ifdef HAVE_READLINK
403		char link[MAXPATHLEN+1];
404		char argv0copy[2*MAXPATHLEN+1];
405		int nr = 0;
406		if (argc > 0 && argv0 != NULL)
407			nr = readlink(argv0, link, MAXPATHLEN);
408		if (nr > 0) {
409			/* It's a symlink */
410			link[nr] = '\0';
411			if (link[0] == SEP)
412				argv0 = link; /* Link to absolute path */
413			else if (strchr(link, SEP) == NULL)
414				; /* Link without path */
415			else {
416				/* Must join(dirname(argv0), link) */
417				char *q = strrchr(argv0, SEP);
418				if (q == NULL)
419					argv0 = link; /* argv0 without path */
420				else {
421					/* Must make a copy */
422					strcpy(argv0copy, argv0);
423					q = strrchr(argv0copy, SEP);
424					strcpy(q+1, link);
425					argv0 = argv0copy;
426				}
427			}
428		}
429#endif /* HAVE_READLINK */
430#if SEP == '\\' /* Special case for MS filename syntax */
431		if (argc > 0 && argv0 != NULL) {
432			char *q;
433			p = strrchr(argv0, SEP);
434			/* Test for alternate separator */
435			q = strrchr(p ? p : argv0, '/');
436			if (q != NULL)
437				p = q;
438			if (p != NULL) {
439				n = p + 1 - argv0;
440				if (n > 1 && p[-1] != ':')
441					n--; /* Drop trailing separator */
442			}
443		}
444#else /* All other filename syntaxes */
445		if (argc > 0 && argv0 != NULL)
446			p = strrchr(argv0, SEP);
447		if (p != NULL) {
448			n = p + 1 - argv0;
449#if SEP == '/' /* Special case for Unix filename syntax */
450			if (n > 1)
451				n--; /* Drop trailing separator */
452#endif /* Unix */
453		}
454#endif /* All others */
455		a = PyString_FromStringAndSize(argv0, n);
456		if (a == NULL)
457			Py_FatalError("no mem for sys.path insertion");
458		if (PyList_Insert(path, 0, a) < 0)
459			Py_FatalError("sys.path.insert(0) failed");
460		Py_DECREF(a);
461	}
462	Py_DECREF(av);
463}
464