• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /* System module */
3 
4 /*
5 Various bits of information used by the interpreter are collected in
6 module 'sys'.
7 Function member:
8 - exit(sts): raise SystemExit
9 Data members:
10 - stdin, stdout, stderr: standard file objects
11 - modules: the table of modules (dictionary)
12 - path: module search path (list of strings)
13 - argv: script arguments (list of strings)
14 - ps1, ps2: optional primary and secondary prompts (strings)
15 */
16 
17 #include "Python.h"
18 #include "internal/pystate.h"
19 #include "code.h"
20 #include "frameobject.h"
21 #include "pythread.h"
22 
23 #include "osdefs.h"
24 #include <locale.h>
25 
26 #ifdef MS_WINDOWS
27 #define WIN32_LEAN_AND_MEAN
28 #include <windows.h>
29 #endif /* MS_WINDOWS */
30 
31 #ifdef MS_COREDLL
32 extern void *PyWin_DLLhModule;
33 /* A string loaded from the DLL at startup: */
34 extern const char *PyWin_DLLVersionString;
35 #endif
36 
37 /*[clinic input]
38 module sys
39 [clinic start generated code]*/
40 /*[clinic end generated code: output=da39a3ee5e6b4b0d input=3726b388feee8cea]*/
41 
42 #include "clinic/sysmodule.c.h"
43 
44 _Py_IDENTIFIER(_);
45 _Py_IDENTIFIER(__sizeof__);
46 _Py_IDENTIFIER(_xoptions);
47 _Py_IDENTIFIER(buffer);
48 _Py_IDENTIFIER(builtins);
49 _Py_IDENTIFIER(encoding);
50 _Py_IDENTIFIER(path);
51 _Py_IDENTIFIER(stdout);
52 _Py_IDENTIFIER(stderr);
53 _Py_IDENTIFIER(warnoptions);
54 _Py_IDENTIFIER(write);
55 
56 PyObject *
_PySys_GetObjectId(_Py_Identifier * key)57 _PySys_GetObjectId(_Py_Identifier *key)
58 {
59     PyThreadState *tstate = PyThreadState_GET();
60     PyObject *sd = tstate->interp->sysdict;
61     if (sd == NULL)
62         return NULL;
63     return _PyDict_GetItemId(sd, key);
64 }
65 
66 PyObject *
PySys_GetObject(const char * name)67 PySys_GetObject(const char *name)
68 {
69     PyThreadState *tstate = PyThreadState_GET();
70     PyObject *sd = tstate->interp->sysdict;
71     if (sd == NULL)
72         return NULL;
73     return PyDict_GetItemString(sd, name);
74 }
75 
76 int
_PySys_SetObjectId(_Py_Identifier * key,PyObject * v)77 _PySys_SetObjectId(_Py_Identifier *key, PyObject *v)
78 {
79     PyThreadState *tstate = PyThreadState_GET();
80     PyObject *sd = tstate->interp->sysdict;
81     if (v == NULL) {
82         if (_PyDict_GetItemId(sd, key) == NULL)
83             return 0;
84         else
85             return _PyDict_DelItemId(sd, key);
86     }
87     else
88         return _PyDict_SetItemId(sd, key, v);
89 }
90 
91 int
PySys_SetObject(const char * name,PyObject * v)92 PySys_SetObject(const char *name, PyObject *v)
93 {
94     PyThreadState *tstate = PyThreadState_GET();
95     PyObject *sd = tstate->interp->sysdict;
96     if (v == NULL) {
97         if (PyDict_GetItemString(sd, name) == NULL)
98             return 0;
99         else
100             return PyDict_DelItemString(sd, name);
101     }
102     else
103         return PyDict_SetItemString(sd, name, v);
104 }
105 
106 static PyObject *
sys_breakpointhook(PyObject * self,PyObject * const * args,Py_ssize_t nargs,PyObject * keywords)107 sys_breakpointhook(PyObject *self, PyObject *const *args, Py_ssize_t nargs, PyObject *keywords)
108 {
109     assert(!PyErr_Occurred());
110     char *envar = Py_GETENV("PYTHONBREAKPOINT");
111 
112     if (envar == NULL || strlen(envar) == 0) {
113         envar = "pdb.set_trace";
114     }
115     else if (!strcmp(envar, "0")) {
116         /* The breakpoint is explicitly no-op'd. */
117         Py_RETURN_NONE;
118     }
119     /* According to POSIX the string returned by getenv() might be invalidated
120      * or the string content might be overwritten by a subsequent call to
121      * getenv().  Since importing a module can performs the getenv() calls,
122      * we need to save a copy of envar. */
123     envar = _PyMem_RawStrdup(envar);
124     if (envar == NULL) {
125         PyErr_NoMemory();
126         return NULL;
127     }
128     const char *last_dot = strrchr(envar, '.');
129     const char *attrname = NULL;
130     PyObject *modulepath = NULL;
131 
132     if (last_dot == NULL) {
133         /* The breakpoint is a built-in, e.g. PYTHONBREAKPOINT=int */
134         modulepath = PyUnicode_FromString("builtins");
135         attrname = envar;
136     }
137     else if (last_dot != envar) {
138         /* Split on the last dot; */
139         modulepath = PyUnicode_FromStringAndSize(envar, last_dot - envar);
140         attrname = last_dot + 1;
141     }
142     else {
143         goto warn;
144     }
145     if (modulepath == NULL) {
146         PyMem_RawFree(envar);
147         return NULL;
148     }
149 
150     PyObject *fromlist = Py_BuildValue("(s)", attrname);
151     if (fromlist == NULL) {
152         Py_DECREF(modulepath);
153         PyMem_RawFree(envar);
154         return NULL;
155     }
156     PyObject *module = PyImport_ImportModuleLevelObject(
157         modulepath, NULL, NULL, fromlist, 0);
158     Py_DECREF(modulepath);
159     Py_DECREF(fromlist);
160 
161     if (module == NULL) {
162         if (PyErr_ExceptionMatches(PyExc_ImportError)) {
163             goto warn;
164         }
165         PyMem_RawFree(envar);
166         return NULL;
167     }
168 
169     PyObject *hook = PyObject_GetAttrString(module, attrname);
170     Py_DECREF(module);
171 
172     if (hook == NULL) {
173         if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
174             goto warn;
175         }
176         PyMem_RawFree(envar);
177         return NULL;
178     }
179     PyMem_RawFree(envar);
180     PyObject *retval = _PyObject_FastCallKeywords(hook, args, nargs, keywords);
181     Py_DECREF(hook);
182     return retval;
183 
184   warn:
185     /* If any of the imports went wrong, then warn and ignore. */
186     PyErr_Clear();
187     int status = PyErr_WarnFormat(
188         PyExc_RuntimeWarning, 0,
189         "Ignoring unimportable $PYTHONBREAKPOINT: \"%s\"", envar);
190     PyMem_RawFree(envar);
191     if (status < 0) {
192         /* Printing the warning raised an exception. */
193         return NULL;
194     }
195     /* The warning was (probably) issued. */
196     Py_RETURN_NONE;
197 }
198 
199 PyDoc_STRVAR(breakpointhook_doc,
200 "breakpointhook(*args, **kws)\n"
201 "\n"
202 "This hook function is called by built-in breakpoint().\n"
203 );
204 
205 /* Write repr(o) to sys.stdout using sys.stdout.encoding and 'backslashreplace'
206    error handler. If sys.stdout has a buffer attribute, use
207    sys.stdout.buffer.write(encoded), otherwise redecode the string and use
208    sys.stdout.write(redecoded).
209 
210    Helper function for sys_displayhook(). */
211 static int
sys_displayhook_unencodable(PyObject * outf,PyObject * o)212 sys_displayhook_unencodable(PyObject *outf, PyObject *o)
213 {
214     PyObject *stdout_encoding = NULL;
215     PyObject *encoded, *escaped_str, *repr_str, *buffer, *result;
216     const char *stdout_encoding_str;
217     int ret;
218 
219     stdout_encoding = _PyObject_GetAttrId(outf, &PyId_encoding);
220     if (stdout_encoding == NULL)
221         goto error;
222     stdout_encoding_str = PyUnicode_AsUTF8(stdout_encoding);
223     if (stdout_encoding_str == NULL)
224         goto error;
225 
226     repr_str = PyObject_Repr(o);
227     if (repr_str == NULL)
228         goto error;
229     encoded = PyUnicode_AsEncodedString(repr_str,
230                                         stdout_encoding_str,
231                                         "backslashreplace");
232     Py_DECREF(repr_str);
233     if (encoded == NULL)
234         goto error;
235 
236     buffer = _PyObject_GetAttrId(outf, &PyId_buffer);
237     if (buffer) {
238         result = _PyObject_CallMethodIdObjArgs(buffer, &PyId_write, encoded, NULL);
239         Py_DECREF(buffer);
240         Py_DECREF(encoded);
241         if (result == NULL)
242             goto error;
243         Py_DECREF(result);
244     }
245     else {
246         PyErr_Clear();
247         escaped_str = PyUnicode_FromEncodedObject(encoded,
248                                                   stdout_encoding_str,
249                                                   "strict");
250         Py_DECREF(encoded);
251         if (PyFile_WriteObject(escaped_str, outf, Py_PRINT_RAW) != 0) {
252             Py_DECREF(escaped_str);
253             goto error;
254         }
255         Py_DECREF(escaped_str);
256     }
257     ret = 0;
258     goto finally;
259 
260 error:
261     ret = -1;
262 finally:
263     Py_XDECREF(stdout_encoding);
264     return ret;
265 }
266 
267 static PyObject *
sys_displayhook(PyObject * self,PyObject * o)268 sys_displayhook(PyObject *self, PyObject *o)
269 {
270     PyObject *outf;
271     PyObject *builtins;
272     static PyObject *newline = NULL;
273     int err;
274 
275     builtins = _PyImport_GetModuleId(&PyId_builtins);
276     if (builtins == NULL) {
277         PyErr_SetString(PyExc_RuntimeError, "lost builtins module");
278         return NULL;
279     }
280     Py_DECREF(builtins);
281 
282     /* Print value except if None */
283     /* After printing, also assign to '_' */
284     /* Before, set '_' to None to avoid recursion */
285     if (o == Py_None) {
286         Py_RETURN_NONE;
287     }
288     if (_PyObject_SetAttrId(builtins, &PyId__, Py_None) != 0)
289         return NULL;
290     outf = _PySys_GetObjectId(&PyId_stdout);
291     if (outf == NULL || outf == Py_None) {
292         PyErr_SetString(PyExc_RuntimeError, "lost sys.stdout");
293         return NULL;
294     }
295     if (PyFile_WriteObject(o, outf, 0) != 0) {
296         if (PyErr_ExceptionMatches(PyExc_UnicodeEncodeError)) {
297             /* repr(o) is not encodable to sys.stdout.encoding with
298              * sys.stdout.errors error handler (which is probably 'strict') */
299             PyErr_Clear();
300             err = sys_displayhook_unencodable(outf, o);
301             if (err)
302                 return NULL;
303         }
304         else {
305             return NULL;
306         }
307     }
308     if (newline == NULL) {
309         newline = PyUnicode_FromString("\n");
310         if (newline == NULL)
311             return NULL;
312     }
313     if (PyFile_WriteObject(newline, outf, Py_PRINT_RAW) != 0)
314         return NULL;
315     if (_PyObject_SetAttrId(builtins, &PyId__, o) != 0)
316         return NULL;
317     Py_RETURN_NONE;
318 }
319 
320 PyDoc_STRVAR(displayhook_doc,
321 "displayhook(object) -> None\n"
322 "\n"
323 "Print an object to sys.stdout and also save it in builtins._\n"
324 );
325 
326 static PyObject *
sys_excepthook(PyObject * self,PyObject * args)327 sys_excepthook(PyObject* self, PyObject* args)
328 {
329     PyObject *exc, *value, *tb;
330     if (!PyArg_UnpackTuple(args, "excepthook", 3, 3, &exc, &value, &tb))
331         return NULL;
332     PyErr_Display(exc, value, tb);
333     Py_RETURN_NONE;
334 }
335 
336 PyDoc_STRVAR(excepthook_doc,
337 "excepthook(exctype, value, traceback) -> None\n"
338 "\n"
339 "Handle an exception by displaying it with a traceback on sys.stderr.\n"
340 );
341 
342 static PyObject *
sys_exc_info(PyObject * self,PyObject * noargs)343 sys_exc_info(PyObject *self, PyObject *noargs)
344 {
345     _PyErr_StackItem *err_info = _PyErr_GetTopmostException(PyThreadState_GET());
346     return Py_BuildValue(
347         "(OOO)",
348         err_info->exc_type != NULL ? err_info->exc_type : Py_None,
349         err_info->exc_value != NULL ? err_info->exc_value : Py_None,
350         err_info->exc_traceback != NULL ?
351             err_info->exc_traceback : Py_None);
352 }
353 
354 PyDoc_STRVAR(exc_info_doc,
355 "exc_info() -> (type, value, traceback)\n\
356 \n\
357 Return information about the most recent exception caught by an except\n\
358 clause in the current stack frame or in an older stack frame."
359 );
360 
361 static PyObject *
sys_exit(PyObject * self,PyObject * args)362 sys_exit(PyObject *self, PyObject *args)
363 {
364     PyObject *exit_code = 0;
365     if (!PyArg_UnpackTuple(args, "exit", 0, 1, &exit_code))
366         return NULL;
367     /* Raise SystemExit so callers may catch it or clean up. */
368     PyErr_SetObject(PyExc_SystemExit, exit_code);
369     return NULL;
370 }
371 
372 PyDoc_STRVAR(exit_doc,
373 "exit([status])\n\
374 \n\
375 Exit the interpreter by raising SystemExit(status).\n\
376 If the status is omitted or None, it defaults to zero (i.e., success).\n\
377 If the status is an integer, it will be used as the system exit status.\n\
378 If it is another kind of object, it will be printed and the system\n\
379 exit status will be one (i.e., failure)."
380 );
381 
382 
383 static PyObject *
sys_getdefaultencoding(PyObject * self)384 sys_getdefaultencoding(PyObject *self)
385 {
386     return PyUnicode_FromString(PyUnicode_GetDefaultEncoding());
387 }
388 
389 PyDoc_STRVAR(getdefaultencoding_doc,
390 "getdefaultencoding() -> string\n\
391 \n\
392 Return the current default string encoding used by the Unicode \n\
393 implementation."
394 );
395 
396 static PyObject *
sys_getfilesystemencoding(PyObject * self)397 sys_getfilesystemencoding(PyObject *self)
398 {
399     if (Py_FileSystemDefaultEncoding)
400         return PyUnicode_FromString(Py_FileSystemDefaultEncoding);
401     PyErr_SetString(PyExc_RuntimeError,
402                     "filesystem encoding is not initialized");
403     return NULL;
404 }
405 
406 PyDoc_STRVAR(getfilesystemencoding_doc,
407 "getfilesystemencoding() -> string\n\
408 \n\
409 Return the encoding used to convert Unicode filenames in\n\
410 operating system filenames."
411 );
412 
413 static PyObject *
sys_getfilesystemencodeerrors(PyObject * self)414 sys_getfilesystemencodeerrors(PyObject *self)
415 {
416     if (Py_FileSystemDefaultEncodeErrors)
417         return PyUnicode_FromString(Py_FileSystemDefaultEncodeErrors);
418     PyErr_SetString(PyExc_RuntimeError,
419         "filesystem encoding is not initialized");
420     return NULL;
421 }
422 
423 PyDoc_STRVAR(getfilesystemencodeerrors_doc,
424     "getfilesystemencodeerrors() -> string\n\
425 \n\
426 Return the error mode used to convert Unicode filenames in\n\
427 operating system filenames."
428 );
429 
430 static PyObject *
sys_intern(PyObject * self,PyObject * args)431 sys_intern(PyObject *self, PyObject *args)
432 {
433     PyObject *s;
434     if (!PyArg_ParseTuple(args, "U:intern", &s))
435         return NULL;
436     if (PyUnicode_CheckExact(s)) {
437         Py_INCREF(s);
438         PyUnicode_InternInPlace(&s);
439         return s;
440     }
441     else {
442         PyErr_Format(PyExc_TypeError,
443                         "can't intern %.400s", s->ob_type->tp_name);
444         return NULL;
445     }
446 }
447 
448 PyDoc_STRVAR(intern_doc,
449 "intern(string) -> string\n\
450 \n\
451 ``Intern'' the given string.  This enters the string in the (global)\n\
452 table of interned strings whose purpose is to speed up dictionary lookups.\n\
453 Return the string itself or the previously interned string object with the\n\
454 same value.");
455 
456 
457 /*
458  * Cached interned string objects used for calling the profile and
459  * trace functions.  Initialized by trace_init().
460  */
461 static PyObject *whatstrings[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
462 
463 static int
trace_init(void)464 trace_init(void)
465 {
466     static const char * const whatnames[8] = {
467         "call", "exception", "line", "return",
468         "c_call", "c_exception", "c_return",
469         "opcode"
470     };
471     PyObject *name;
472     int i;
473     for (i = 0; i < 8; ++i) {
474         if (whatstrings[i] == NULL) {
475             name = PyUnicode_InternFromString(whatnames[i]);
476             if (name == NULL)
477                 return -1;
478             whatstrings[i] = name;
479         }
480     }
481     return 0;
482 }
483 
484 
485 static PyObject *
call_trampoline(PyObject * callback,PyFrameObject * frame,int what,PyObject * arg)486 call_trampoline(PyObject* callback,
487                 PyFrameObject *frame, int what, PyObject *arg)
488 {
489     PyObject *result;
490     PyObject *stack[3];
491 
492     if (PyFrame_FastToLocalsWithError(frame) < 0) {
493         return NULL;
494     }
495 
496     stack[0] = (PyObject *)frame;
497     stack[1] = whatstrings[what];
498     stack[2] = (arg != NULL) ? arg : Py_None;
499 
500     /* call the Python-level function */
501     result = _PyObject_FastCall(callback, stack, 3);
502 
503     PyFrame_LocalsToFast(frame, 1);
504     if (result == NULL) {
505         PyTraceBack_Here(frame);
506     }
507 
508     return result;
509 }
510 
511 static int
profile_trampoline(PyObject * self,PyFrameObject * frame,int what,PyObject * arg)512 profile_trampoline(PyObject *self, PyFrameObject *frame,
513                    int what, PyObject *arg)
514 {
515     PyObject *result;
516 
517     if (arg == NULL)
518         arg = Py_None;
519     result = call_trampoline(self, frame, what, arg);
520     if (result == NULL) {
521         PyEval_SetProfile(NULL, NULL);
522         return -1;
523     }
524     Py_DECREF(result);
525     return 0;
526 }
527 
528 static int
trace_trampoline(PyObject * self,PyFrameObject * frame,int what,PyObject * arg)529 trace_trampoline(PyObject *self, PyFrameObject *frame,
530                  int what, PyObject *arg)
531 {
532     PyObject *callback;
533     PyObject *result;
534 
535     if (what == PyTrace_CALL)
536         callback = self;
537     else
538         callback = frame->f_trace;
539     if (callback == NULL)
540         return 0;
541     result = call_trampoline(callback, frame, what, arg);
542     if (result == NULL) {
543         PyEval_SetTrace(NULL, NULL);
544         Py_CLEAR(frame->f_trace);
545         return -1;
546     }
547     if (result != Py_None) {
548         Py_XSETREF(frame->f_trace, result);
549     }
550     else {
551         Py_DECREF(result);
552     }
553     return 0;
554 }
555 
556 static PyObject *
sys_settrace(PyObject * self,PyObject * args)557 sys_settrace(PyObject *self, PyObject *args)
558 {
559     if (trace_init() == -1)
560         return NULL;
561     if (args == Py_None)
562         PyEval_SetTrace(NULL, NULL);
563     else
564         PyEval_SetTrace(trace_trampoline, args);
565     Py_RETURN_NONE;
566 }
567 
568 PyDoc_STRVAR(settrace_doc,
569 "settrace(function)\n\
570 \n\
571 Set the global debug tracing function.  It will be called on each\n\
572 function call.  See the debugger chapter in the library manual."
573 );
574 
575 static PyObject *
sys_gettrace(PyObject * self,PyObject * args)576 sys_gettrace(PyObject *self, PyObject *args)
577 {
578     PyThreadState *tstate = PyThreadState_GET();
579     PyObject *temp = tstate->c_traceobj;
580 
581     if (temp == NULL)
582         temp = Py_None;
583     Py_INCREF(temp);
584     return temp;
585 }
586 
587 PyDoc_STRVAR(gettrace_doc,
588 "gettrace()\n\
589 \n\
590 Return the global debug tracing function set with sys.settrace.\n\
591 See the debugger chapter in the library manual."
592 );
593 
594 static PyObject *
sys_setprofile(PyObject * self,PyObject * args)595 sys_setprofile(PyObject *self, PyObject *args)
596 {
597     if (trace_init() == -1)
598         return NULL;
599     if (args == Py_None)
600         PyEval_SetProfile(NULL, NULL);
601     else
602         PyEval_SetProfile(profile_trampoline, args);
603     Py_RETURN_NONE;
604 }
605 
606 PyDoc_STRVAR(setprofile_doc,
607 "setprofile(function)\n\
608 \n\
609 Set the profiling function.  It will be called on each function call\n\
610 and return.  See the profiler chapter in the library manual."
611 );
612 
613 static PyObject *
sys_getprofile(PyObject * self,PyObject * args)614 sys_getprofile(PyObject *self, PyObject *args)
615 {
616     PyThreadState *tstate = PyThreadState_GET();
617     PyObject *temp = tstate->c_profileobj;
618 
619     if (temp == NULL)
620         temp = Py_None;
621     Py_INCREF(temp);
622     return temp;
623 }
624 
625 PyDoc_STRVAR(getprofile_doc,
626 "getprofile()\n\
627 \n\
628 Return the profiling function set with sys.setprofile.\n\
629 See the profiler chapter in the library manual."
630 );
631 
632 static PyObject *
sys_setcheckinterval(PyObject * self,PyObject * args)633 sys_setcheckinterval(PyObject *self, PyObject *args)
634 {
635     if (PyErr_WarnEx(PyExc_DeprecationWarning,
636                      "sys.getcheckinterval() and sys.setcheckinterval() "
637                      "are deprecated.  Use sys.setswitchinterval() "
638                      "instead.", 1) < 0)
639         return NULL;
640     PyInterpreterState *interp = PyThreadState_GET()->interp;
641     if (!PyArg_ParseTuple(args, "i:setcheckinterval", &interp->check_interval))
642         return NULL;
643     Py_RETURN_NONE;
644 }
645 
646 PyDoc_STRVAR(setcheckinterval_doc,
647 "setcheckinterval(n)\n\
648 \n\
649 Tell the Python interpreter to check for asynchronous events every\n\
650 n instructions.  This also affects how often thread switches occur."
651 );
652 
653 static PyObject *
sys_getcheckinterval(PyObject * self,PyObject * args)654 sys_getcheckinterval(PyObject *self, PyObject *args)
655 {
656     if (PyErr_WarnEx(PyExc_DeprecationWarning,
657                      "sys.getcheckinterval() and sys.setcheckinterval() "
658                      "are deprecated.  Use sys.getswitchinterval() "
659                      "instead.", 1) < 0)
660         return NULL;
661     PyInterpreterState *interp = PyThreadState_GET()->interp;
662     return PyLong_FromLong(interp->check_interval);
663 }
664 
665 PyDoc_STRVAR(getcheckinterval_doc,
666 "getcheckinterval() -> current check interval; see setcheckinterval()."
667 );
668 
669 static PyObject *
sys_setswitchinterval(PyObject * self,PyObject * args)670 sys_setswitchinterval(PyObject *self, PyObject *args)
671 {
672     double d;
673     if (!PyArg_ParseTuple(args, "d:setswitchinterval", &d))
674         return NULL;
675     if (d <= 0.0) {
676         PyErr_SetString(PyExc_ValueError,
677                         "switch interval must be strictly positive");
678         return NULL;
679     }
680     _PyEval_SetSwitchInterval((unsigned long) (1e6 * d));
681     Py_RETURN_NONE;
682 }
683 
684 PyDoc_STRVAR(setswitchinterval_doc,
685 "setswitchinterval(n)\n\
686 \n\
687 Set the ideal thread switching delay inside the Python interpreter\n\
688 The actual frequency of switching threads can be lower if the\n\
689 interpreter executes long sequences of uninterruptible code\n\
690 (this is implementation-specific and workload-dependent).\n\
691 \n\
692 The parameter must represent the desired switching delay in seconds\n\
693 A typical value is 0.005 (5 milliseconds)."
694 );
695 
696 static PyObject *
sys_getswitchinterval(PyObject * self,PyObject * args)697 sys_getswitchinterval(PyObject *self, PyObject *args)
698 {
699     return PyFloat_FromDouble(1e-6 * _PyEval_GetSwitchInterval());
700 }
701 
702 PyDoc_STRVAR(getswitchinterval_doc,
703 "getswitchinterval() -> current thread switch interval; see setswitchinterval()."
704 );
705 
706 static PyObject *
sys_setrecursionlimit(PyObject * self,PyObject * args)707 sys_setrecursionlimit(PyObject *self, PyObject *args)
708 {
709     int new_limit, mark;
710     PyThreadState *tstate;
711 
712     if (!PyArg_ParseTuple(args, "i:setrecursionlimit", &new_limit))
713         return NULL;
714 
715     if (new_limit < 1) {
716         PyErr_SetString(PyExc_ValueError,
717                         "recursion limit must be greater or equal than 1");
718         return NULL;
719     }
720 
721     /* Issue #25274: When the recursion depth hits the recursion limit in
722        _Py_CheckRecursiveCall(), the overflowed flag of the thread state is
723        set to 1 and a RecursionError is raised. The overflowed flag is reset
724        to 0 when the recursion depth goes below the low-water mark: see
725        Py_LeaveRecursiveCall().
726 
727        Reject too low new limit if the current recursion depth is higher than
728        the new low-water mark. Otherwise it may not be possible anymore to
729        reset the overflowed flag to 0. */
730     mark = _Py_RecursionLimitLowerWaterMark(new_limit);
731     tstate = PyThreadState_GET();
732     if (tstate->recursion_depth >= mark) {
733         PyErr_Format(PyExc_RecursionError,
734                      "cannot set the recursion limit to %i at "
735                      "the recursion depth %i: the limit is too low",
736                      new_limit, tstate->recursion_depth);
737         return NULL;
738     }
739 
740     Py_SetRecursionLimit(new_limit);
741     Py_RETURN_NONE;
742 }
743 
744 /*[clinic input]
745 sys.set_coroutine_origin_tracking_depth
746 
747   depth: int
748 
749 Enable or disable origin tracking for coroutine objects in this thread.
750 
751 Coroutine objects will track 'depth' frames of traceback information about
752 where they came from, available in their cr_origin attribute. Set depth of 0
753 to disable.
754 [clinic start generated code]*/
755 
756 static PyObject *
sys_set_coroutine_origin_tracking_depth_impl(PyObject * module,int depth)757 sys_set_coroutine_origin_tracking_depth_impl(PyObject *module, int depth)
758 /*[clinic end generated code: output=0a2123c1cc6759c5 input=9083112cccc1bdcb]*/
759 {
760     if (depth < 0) {
761         PyErr_SetString(PyExc_ValueError, "depth must be >= 0");
762         return NULL;
763     }
764     _PyEval_SetCoroutineOriginTrackingDepth(depth);
765     Py_RETURN_NONE;
766 }
767 
768 /*[clinic input]
769 sys.get_coroutine_origin_tracking_depth -> int
770 
771 Check status of origin tracking for coroutine objects in this thread.
772 [clinic start generated code]*/
773 
774 static int
sys_get_coroutine_origin_tracking_depth_impl(PyObject * module)775 sys_get_coroutine_origin_tracking_depth_impl(PyObject *module)
776 /*[clinic end generated code: output=3699f7be95a3afb8 input=335266a71205b61a]*/
777 {
778     return _PyEval_GetCoroutineOriginTrackingDepth();
779 }
780 
781 static PyObject *
sys_set_coroutine_wrapper(PyObject * self,PyObject * wrapper)782 sys_set_coroutine_wrapper(PyObject *self, PyObject *wrapper)
783 {
784     if (PyErr_WarnEx(PyExc_DeprecationWarning,
785                      "set_coroutine_wrapper is deprecated", 1) < 0) {
786         return NULL;
787     }
788 
789     if (wrapper != Py_None) {
790         if (!PyCallable_Check(wrapper)) {
791             PyErr_Format(PyExc_TypeError,
792                          "callable expected, got %.50s",
793                          Py_TYPE(wrapper)->tp_name);
794             return NULL;
795         }
796         _PyEval_SetCoroutineWrapper(wrapper);
797     }
798     else {
799         _PyEval_SetCoroutineWrapper(NULL);
800     }
801     Py_RETURN_NONE;
802 }
803 
804 PyDoc_STRVAR(set_coroutine_wrapper_doc,
805 "set_coroutine_wrapper(wrapper)\n\
806 \n\
807 Set a wrapper for coroutine objects."
808 );
809 
810 static PyObject *
sys_get_coroutine_wrapper(PyObject * self,PyObject * args)811 sys_get_coroutine_wrapper(PyObject *self, PyObject *args)
812 {
813     if (PyErr_WarnEx(PyExc_DeprecationWarning,
814                      "get_coroutine_wrapper is deprecated", 1) < 0) {
815         return NULL;
816     }
817     PyObject *wrapper = _PyEval_GetCoroutineWrapper();
818     if (wrapper == NULL) {
819         wrapper = Py_None;
820     }
821     Py_INCREF(wrapper);
822     return wrapper;
823 }
824 
825 PyDoc_STRVAR(get_coroutine_wrapper_doc,
826 "get_coroutine_wrapper()\n\
827 \n\
828 Return the wrapper for coroutine objects set by sys.set_coroutine_wrapper."
829 );
830 
831 
832 static PyTypeObject AsyncGenHooksType;
833 
834 PyDoc_STRVAR(asyncgen_hooks_doc,
835 "asyncgen_hooks\n\
836 \n\
837 A struct sequence providing information about asynhronous\n\
838 generators hooks.  The attributes are read only.");
839 
840 static PyStructSequence_Field asyncgen_hooks_fields[] = {
841     {"firstiter", "Hook to intercept first iteration"},
842     {"finalizer", "Hook to intercept finalization"},
843     {0}
844 };
845 
846 static PyStructSequence_Desc asyncgen_hooks_desc = {
847     "asyncgen_hooks",          /* name */
848     asyncgen_hooks_doc,        /* doc */
849     asyncgen_hooks_fields ,    /* fields */
850     2
851 };
852 
853 
854 static PyObject *
sys_set_asyncgen_hooks(PyObject * self,PyObject * args,PyObject * kw)855 sys_set_asyncgen_hooks(PyObject *self, PyObject *args, PyObject *kw)
856 {
857     static char *keywords[] = {"firstiter", "finalizer", NULL};
858     PyObject *firstiter = NULL;
859     PyObject *finalizer = NULL;
860 
861     if (!PyArg_ParseTupleAndKeywords(
862             args, kw, "|OO", keywords,
863             &firstiter, &finalizer)) {
864         return NULL;
865     }
866 
867     if (finalizer && finalizer != Py_None) {
868         if (!PyCallable_Check(finalizer)) {
869             PyErr_Format(PyExc_TypeError,
870                          "callable finalizer expected, got %.50s",
871                          Py_TYPE(finalizer)->tp_name);
872             return NULL;
873         }
874         _PyEval_SetAsyncGenFinalizer(finalizer);
875     }
876     else if (finalizer == Py_None) {
877         _PyEval_SetAsyncGenFinalizer(NULL);
878     }
879 
880     if (firstiter && firstiter != Py_None) {
881         if (!PyCallable_Check(firstiter)) {
882             PyErr_Format(PyExc_TypeError,
883                          "callable firstiter expected, got %.50s",
884                          Py_TYPE(firstiter)->tp_name);
885             return NULL;
886         }
887         _PyEval_SetAsyncGenFirstiter(firstiter);
888     }
889     else if (firstiter == Py_None) {
890         _PyEval_SetAsyncGenFirstiter(NULL);
891     }
892 
893     Py_RETURN_NONE;
894 }
895 
896 PyDoc_STRVAR(set_asyncgen_hooks_doc,
897 "set_asyncgen_hooks(*, firstiter=None, finalizer=None)\n\
898 \n\
899 Set a finalizer for async generators objects."
900 );
901 
902 static PyObject *
sys_get_asyncgen_hooks(PyObject * self,PyObject * args)903 sys_get_asyncgen_hooks(PyObject *self, PyObject *args)
904 {
905     PyObject *res;
906     PyObject *firstiter = _PyEval_GetAsyncGenFirstiter();
907     PyObject *finalizer = _PyEval_GetAsyncGenFinalizer();
908 
909     res = PyStructSequence_New(&AsyncGenHooksType);
910     if (res == NULL) {
911         return NULL;
912     }
913 
914     if (firstiter == NULL) {
915         firstiter = Py_None;
916     }
917 
918     if (finalizer == NULL) {
919         finalizer = Py_None;
920     }
921 
922     Py_INCREF(firstiter);
923     PyStructSequence_SET_ITEM(res, 0, firstiter);
924 
925     Py_INCREF(finalizer);
926     PyStructSequence_SET_ITEM(res, 1, finalizer);
927 
928     return res;
929 }
930 
931 PyDoc_STRVAR(get_asyncgen_hooks_doc,
932 "get_asyncgen_hooks()\n\
933 \n\
934 Return a namedtuple of installed asynchronous generators hooks \
935 (firstiter, finalizer)."
936 );
937 
938 
939 static PyTypeObject Hash_InfoType;
940 
941 PyDoc_STRVAR(hash_info_doc,
942 "hash_info\n\
943 \n\
944 A struct sequence providing parameters used for computing\n\
945 hashes. The attributes are read only.");
946 
947 static PyStructSequence_Field hash_info_fields[] = {
948     {"width", "width of the type used for hashing, in bits"},
949     {"modulus", "prime number giving the modulus on which the hash "
950                 "function is based"},
951     {"inf", "value to be used for hash of a positive infinity"},
952     {"nan", "value to be used for hash of a nan"},
953     {"imag", "multiplier used for the imaginary part of a complex number"},
954     {"algorithm", "name of the algorithm for hashing of str, bytes and "
955                   "memoryviews"},
956     {"hash_bits", "internal output size of hash algorithm"},
957     {"seed_bits", "seed size of hash algorithm"},
958     {"cutoff", "small string optimization cutoff"},
959     {NULL, NULL}
960 };
961 
962 static PyStructSequence_Desc hash_info_desc = {
963     "sys.hash_info",
964     hash_info_doc,
965     hash_info_fields,
966     9,
967 };
968 
969 static PyObject *
get_hash_info(void)970 get_hash_info(void)
971 {
972     PyObject *hash_info;
973     int field = 0;
974     PyHash_FuncDef *hashfunc;
975     hash_info = PyStructSequence_New(&Hash_InfoType);
976     if (hash_info == NULL)
977         return NULL;
978     hashfunc = PyHash_GetFuncDef();
979     PyStructSequence_SET_ITEM(hash_info, field++,
980                               PyLong_FromLong(8*sizeof(Py_hash_t)));
981     PyStructSequence_SET_ITEM(hash_info, field++,
982                               PyLong_FromSsize_t(_PyHASH_MODULUS));
983     PyStructSequence_SET_ITEM(hash_info, field++,
984                               PyLong_FromLong(_PyHASH_INF));
985     PyStructSequence_SET_ITEM(hash_info, field++,
986                               PyLong_FromLong(_PyHASH_NAN));
987     PyStructSequence_SET_ITEM(hash_info, field++,
988                               PyLong_FromLong(_PyHASH_IMAG));
989     PyStructSequence_SET_ITEM(hash_info, field++,
990                               PyUnicode_FromString(hashfunc->name));
991     PyStructSequence_SET_ITEM(hash_info, field++,
992                               PyLong_FromLong(hashfunc->hash_bits));
993     PyStructSequence_SET_ITEM(hash_info, field++,
994                               PyLong_FromLong(hashfunc->seed_bits));
995     PyStructSequence_SET_ITEM(hash_info, field++,
996                               PyLong_FromLong(Py_HASH_CUTOFF));
997     if (PyErr_Occurred()) {
998         Py_CLEAR(hash_info);
999         return NULL;
1000     }
1001     return hash_info;
1002 }
1003 
1004 
1005 PyDoc_STRVAR(setrecursionlimit_doc,
1006 "setrecursionlimit(n)\n\
1007 \n\
1008 Set the maximum depth of the Python interpreter stack to n.  This\n\
1009 limit prevents infinite recursion from causing an overflow of the C\n\
1010 stack and crashing Python.  The highest possible limit is platform-\n\
1011 dependent."
1012 );
1013 
1014 static PyObject *
sys_getrecursionlimit(PyObject * self)1015 sys_getrecursionlimit(PyObject *self)
1016 {
1017     return PyLong_FromLong(Py_GetRecursionLimit());
1018 }
1019 
1020 PyDoc_STRVAR(getrecursionlimit_doc,
1021 "getrecursionlimit()\n\
1022 \n\
1023 Return the current value of the recursion limit, the maximum depth\n\
1024 of the Python interpreter stack.  This limit prevents infinite\n\
1025 recursion from causing an overflow of the C stack and crashing Python."
1026 );
1027 
1028 #ifdef MS_WINDOWS
1029 PyDoc_STRVAR(getwindowsversion_doc,
1030 "getwindowsversion()\n\
1031 \n\
1032 Return information about the running version of Windows as a named tuple.\n\
1033 The members are named: major, minor, build, platform, service_pack,\n\
1034 service_pack_major, service_pack_minor, suite_mask, and product_type. For\n\
1035 backward compatibility, only the first 5 items are available by indexing.\n\
1036 All elements are numbers, except service_pack and platform_type which are\n\
1037 strings, and platform_version which is a 3-tuple. Platform is always 2.\n\
1038 Product_type may be 1 for a workstation, 2 for a domain controller, 3 for a\n\
1039 server. Platform_version is a 3-tuple containing a version number that is\n\
1040 intended for identifying the OS rather than feature detection."
1041 );
1042 
1043 static PyTypeObject WindowsVersionType = {0, 0, 0, 0, 0, 0};
1044 
1045 static PyStructSequence_Field windows_version_fields[] = {
1046     {"major", "Major version number"},
1047     {"minor", "Minor version number"},
1048     {"build", "Build number"},
1049     {"platform", "Operating system platform"},
1050     {"service_pack", "Latest Service Pack installed on the system"},
1051     {"service_pack_major", "Service Pack major version number"},
1052     {"service_pack_minor", "Service Pack minor version number"},
1053     {"suite_mask", "Bit mask identifying available product suites"},
1054     {"product_type", "System product type"},
1055     {"platform_version", "Diagnostic version number"},
1056     {0}
1057 };
1058 
1059 static PyStructSequence_Desc windows_version_desc = {
1060     "sys.getwindowsversion",  /* name */
1061     getwindowsversion_doc,    /* doc */
1062     windows_version_fields,   /* fields */
1063     5                         /* For backward compatibility,
1064                                  only the first 5 items are accessible
1065                                  via indexing, the rest are name only */
1066 };
1067 
1068 /* Disable deprecation warnings about GetVersionEx as the result is
1069    being passed straight through to the caller, who is responsible for
1070    using it correctly. */
1071 #pragma warning(push)
1072 #pragma warning(disable:4996)
1073 
1074 static PyObject *
sys_getwindowsversion(PyObject * self)1075 sys_getwindowsversion(PyObject *self)
1076 {
1077     PyObject *version;
1078     int pos = 0;
1079     OSVERSIONINFOEX ver;
1080     DWORD realMajor, realMinor, realBuild;
1081     HANDLE hKernel32;
1082     wchar_t kernel32_path[MAX_PATH];
1083     LPVOID verblock;
1084     DWORD verblock_size;
1085 
1086     ver.dwOSVersionInfoSize = sizeof(ver);
1087     if (!GetVersionEx((OSVERSIONINFO*) &ver))
1088         return PyErr_SetFromWindowsErr(0);
1089 
1090     version = PyStructSequence_New(&WindowsVersionType);
1091     if (version == NULL)
1092         return NULL;
1093 
1094     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMajorVersion));
1095     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwMinorVersion));
1096     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwBuildNumber));
1097     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.dwPlatformId));
1098     PyStructSequence_SET_ITEM(version, pos++, PyUnicode_FromString(ver.szCSDVersion));
1099     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMajor));
1100     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wServicePackMinor));
1101     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wSuiteMask));
1102     PyStructSequence_SET_ITEM(version, pos++, PyLong_FromLong(ver.wProductType));
1103 
1104     realMajor = ver.dwMajorVersion;
1105     realMinor = ver.dwMinorVersion;
1106     realBuild = ver.dwBuildNumber;
1107 
1108     // GetVersion will lie if we are running in a compatibility mode.
1109     // We need to read the version info from a system file resource
1110     // to accurately identify the OS version. If we fail for any reason,
1111     // just return whatever GetVersion said.
1112     hKernel32 = GetModuleHandleW(L"kernel32.dll");
1113     if (hKernel32 && GetModuleFileNameW(hKernel32, kernel32_path, MAX_PATH) &&
1114         (verblock_size = GetFileVersionInfoSizeW(kernel32_path, NULL)) &&
1115         (verblock = PyMem_RawMalloc(verblock_size))) {
1116         VS_FIXEDFILEINFO *ffi;
1117         UINT ffi_len;
1118 
1119         if (GetFileVersionInfoW(kernel32_path, 0, verblock_size, verblock) &&
1120             VerQueryValueW(verblock, L"", (LPVOID)&ffi, &ffi_len)) {
1121             realMajor = HIWORD(ffi->dwProductVersionMS);
1122             realMinor = LOWORD(ffi->dwProductVersionMS);
1123             realBuild = HIWORD(ffi->dwProductVersionLS);
1124         }
1125         PyMem_RawFree(verblock);
1126     }
1127     PyStructSequence_SET_ITEM(version, pos++, Py_BuildValue("(kkk)",
1128         realMajor,
1129         realMinor,
1130         realBuild
1131     ));
1132 
1133     if (PyErr_Occurred()) {
1134         Py_DECREF(version);
1135         return NULL;
1136     }
1137 
1138     return version;
1139 }
1140 
1141 #pragma warning(pop)
1142 
1143 PyDoc_STRVAR(enablelegacywindowsfsencoding_doc,
1144 "_enablelegacywindowsfsencoding()\n\
1145 \n\
1146 Changes the default filesystem encoding to mbcs:replace for consistency\n\
1147 with earlier versions of Python. See PEP 529 for more information.\n\
1148 \n\
1149 This is equivalent to defining the PYTHONLEGACYWINDOWSFSENCODING \n\
1150 environment variable before launching Python."
1151 );
1152 
1153 static PyObject *
sys_enablelegacywindowsfsencoding(PyObject * self)1154 sys_enablelegacywindowsfsencoding(PyObject *self)
1155 {
1156     Py_FileSystemDefaultEncoding = "mbcs";
1157     Py_FileSystemDefaultEncodeErrors = "replace";
1158     Py_RETURN_NONE;
1159 }
1160 
1161 #endif /* MS_WINDOWS */
1162 
1163 #ifdef HAVE_DLOPEN
1164 static PyObject *
sys_setdlopenflags(PyObject * self,PyObject * args)1165 sys_setdlopenflags(PyObject *self, PyObject *args)
1166 {
1167     int new_val;
1168     PyThreadState *tstate = PyThreadState_GET();
1169     if (!PyArg_ParseTuple(args, "i:setdlopenflags", &new_val))
1170         return NULL;
1171     if (!tstate)
1172         return NULL;
1173     tstate->interp->dlopenflags = new_val;
1174     Py_RETURN_NONE;
1175 }
1176 
1177 PyDoc_STRVAR(setdlopenflags_doc,
1178 "setdlopenflags(n) -> None\n\
1179 \n\
1180 Set the flags used by the interpreter for dlopen calls, such as when the\n\
1181 interpreter loads extension modules.  Among other things, this will enable\n\
1182 a lazy resolving of symbols when importing a module, if called as\n\
1183 sys.setdlopenflags(0).  To share symbols across extension modules, call as\n\
1184 sys.setdlopenflags(os.RTLD_GLOBAL).  Symbolic names for the flag modules\n\
1185 can be found in the os module (RTLD_xxx constants, e.g. os.RTLD_LAZY).");
1186 
1187 static PyObject *
sys_getdlopenflags(PyObject * self,PyObject * args)1188 sys_getdlopenflags(PyObject *self, PyObject *args)
1189 {
1190     PyThreadState *tstate = PyThreadState_GET();
1191     if (!tstate)
1192         return NULL;
1193     return PyLong_FromLong(tstate->interp->dlopenflags);
1194 }
1195 
1196 PyDoc_STRVAR(getdlopenflags_doc,
1197 "getdlopenflags() -> int\n\
1198 \n\
1199 Return the current value of the flags that are used for dlopen calls.\n\
1200 The flag constants are defined in the os module.");
1201 
1202 #endif  /* HAVE_DLOPEN */
1203 
1204 #ifdef USE_MALLOPT
1205 /* Link with -lmalloc (or -lmpc) on an SGI */
1206 #include <malloc.h>
1207 
1208 static PyObject *
sys_mdebug(PyObject * self,PyObject * args)1209 sys_mdebug(PyObject *self, PyObject *args)
1210 {
1211     int flag;
1212     if (!PyArg_ParseTuple(args, "i:mdebug", &flag))
1213         return NULL;
1214     mallopt(M_DEBUG, flag);
1215     Py_RETURN_NONE;
1216 }
1217 #endif /* USE_MALLOPT */
1218 
1219 size_t
_PySys_GetSizeOf(PyObject * o)1220 _PySys_GetSizeOf(PyObject *o)
1221 {
1222     PyObject *res = NULL;
1223     PyObject *method;
1224     Py_ssize_t size;
1225 
1226     /* Make sure the type is initialized. float gets initialized late */
1227     if (PyType_Ready(Py_TYPE(o)) < 0)
1228         return (size_t)-1;
1229 
1230     method = _PyObject_LookupSpecial(o, &PyId___sizeof__);
1231     if (method == NULL) {
1232         if (!PyErr_Occurred())
1233             PyErr_Format(PyExc_TypeError,
1234                          "Type %.100s doesn't define __sizeof__",
1235                          Py_TYPE(o)->tp_name);
1236     }
1237     else {
1238         res = _PyObject_CallNoArg(method);
1239         Py_DECREF(method);
1240     }
1241 
1242     if (res == NULL)
1243         return (size_t)-1;
1244 
1245     size = PyLong_AsSsize_t(res);
1246     Py_DECREF(res);
1247     if (size == -1 && PyErr_Occurred())
1248         return (size_t)-1;
1249 
1250     if (size < 0) {
1251         PyErr_SetString(PyExc_ValueError, "__sizeof__() should return >= 0");
1252         return (size_t)-1;
1253     }
1254 
1255     /* add gc_head size */
1256     if (PyObject_IS_GC(o))
1257         return ((size_t)size) + sizeof(PyGC_Head);
1258     return (size_t)size;
1259 }
1260 
1261 static PyObject *
sys_getsizeof(PyObject * self,PyObject * args,PyObject * kwds)1262 sys_getsizeof(PyObject *self, PyObject *args, PyObject *kwds)
1263 {
1264     static char *kwlist[] = {"object", "default", 0};
1265     size_t size;
1266     PyObject *o, *dflt = NULL;
1267 
1268     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:getsizeof",
1269                                      kwlist, &o, &dflt))
1270         return NULL;
1271 
1272     size = _PySys_GetSizeOf(o);
1273 
1274     if (size == (size_t)-1 && PyErr_Occurred()) {
1275         /* Has a default value been given */
1276         if (dflt != NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
1277             PyErr_Clear();
1278             Py_INCREF(dflt);
1279             return dflt;
1280         }
1281         else
1282             return NULL;
1283     }
1284 
1285     return PyLong_FromSize_t(size);
1286 }
1287 
1288 PyDoc_STRVAR(getsizeof_doc,
1289 "getsizeof(object, default) -> int\n\
1290 \n\
1291 Return the size of object in bytes.");
1292 
1293 static PyObject *
sys_getrefcount(PyObject * self,PyObject * arg)1294 sys_getrefcount(PyObject *self, PyObject *arg)
1295 {
1296     return PyLong_FromSsize_t(arg->ob_refcnt);
1297 }
1298 
1299 #ifdef Py_REF_DEBUG
1300 static PyObject *
sys_gettotalrefcount(PyObject * self)1301 sys_gettotalrefcount(PyObject *self)
1302 {
1303     return PyLong_FromSsize_t(_Py_GetRefTotal());
1304 }
1305 #endif /* Py_REF_DEBUG */
1306 
1307 PyDoc_STRVAR(getrefcount_doc,
1308 "getrefcount(object) -> integer\n\
1309 \n\
1310 Return the reference count of object.  The count returned is generally\n\
1311 one higher than you might expect, because it includes the (temporary)\n\
1312 reference as an argument to getrefcount()."
1313 );
1314 
1315 static PyObject *
sys_getallocatedblocks(PyObject * self)1316 sys_getallocatedblocks(PyObject *self)
1317 {
1318     return PyLong_FromSsize_t(_Py_GetAllocatedBlocks());
1319 }
1320 
1321 PyDoc_STRVAR(getallocatedblocks_doc,
1322 "getallocatedblocks() -> integer\n\
1323 \n\
1324 Return the number of memory blocks currently allocated, regardless of their\n\
1325 size."
1326 );
1327 
1328 #ifdef COUNT_ALLOCS
1329 static PyObject *
sys_getcounts(PyObject * self)1330 sys_getcounts(PyObject *self)
1331 {
1332     extern PyObject *get_counts(void);
1333 
1334     return get_counts();
1335 }
1336 #endif
1337 
1338 PyDoc_STRVAR(getframe_doc,
1339 "_getframe([depth]) -> frameobject\n\
1340 \n\
1341 Return a frame object from the call stack.  If optional integer depth is\n\
1342 given, return the frame object that many calls below the top of the stack.\n\
1343 If that is deeper than the call stack, ValueError is raised.  The default\n\
1344 for depth is zero, returning the frame at the top of the call stack.\n\
1345 \n\
1346 This function should be used for internal and specialized\n\
1347 purposes only."
1348 );
1349 
1350 static PyObject *
sys_getframe(PyObject * self,PyObject * args)1351 sys_getframe(PyObject *self, PyObject *args)
1352 {
1353     PyFrameObject *f = PyThreadState_GET()->frame;
1354     int depth = -1;
1355 
1356     if (!PyArg_ParseTuple(args, "|i:_getframe", &depth))
1357         return NULL;
1358 
1359     while (depth > 0 && f != NULL) {
1360         f = f->f_back;
1361         --depth;
1362     }
1363     if (f == NULL) {
1364         PyErr_SetString(PyExc_ValueError,
1365                         "call stack is not deep enough");
1366         return NULL;
1367     }
1368     Py_INCREF(f);
1369     return (PyObject*)f;
1370 }
1371 
1372 PyDoc_STRVAR(current_frames_doc,
1373 "_current_frames() -> dictionary\n\
1374 \n\
1375 Return a dictionary mapping each current thread T's thread id to T's\n\
1376 current stack frame.\n\
1377 \n\
1378 This function should be used for specialized purposes only."
1379 );
1380 
1381 static PyObject *
sys_current_frames(PyObject * self,PyObject * noargs)1382 sys_current_frames(PyObject *self, PyObject *noargs)
1383 {
1384     return _PyThread_CurrentFrames();
1385 }
1386 
1387 PyDoc_STRVAR(call_tracing_doc,
1388 "call_tracing(func, args) -> object\n\
1389 \n\
1390 Call func(*args), while tracing is enabled.  The tracing state is\n\
1391 saved, and restored afterwards.  This is intended to be called from\n\
1392 a debugger from a checkpoint, to recursively debug some other code."
1393 );
1394 
1395 static PyObject *
sys_call_tracing(PyObject * self,PyObject * args)1396 sys_call_tracing(PyObject *self, PyObject *args)
1397 {
1398     PyObject *func, *funcargs;
1399     if (!PyArg_ParseTuple(args, "OO!:call_tracing", &func, &PyTuple_Type, &funcargs))
1400         return NULL;
1401     return _PyEval_CallTracing(func, funcargs);
1402 }
1403 
1404 PyDoc_STRVAR(callstats_doc,
1405 "callstats() -> tuple of integers\n\
1406 \n\
1407 Return a tuple of function call statistics, if CALL_PROFILE was defined\n\
1408 when Python was built.  Otherwise, return None.\n\
1409 \n\
1410 When enabled, this function returns detailed, implementation-specific\n\
1411 details about the number of function calls executed. The return value is\n\
1412 a 11-tuple where the entries in the tuple are counts of:\n\
1413 0. all function calls\n\
1414 1. calls to PyFunction_Type objects\n\
1415 2. PyFunction calls that do not create an argument tuple\n\
1416 3. PyFunction calls that do not create an argument tuple\n\
1417    and bypass PyEval_EvalCodeEx()\n\
1418 4. PyMethod calls\n\
1419 5. PyMethod calls on bound methods\n\
1420 6. PyType calls\n\
1421 7. PyCFunction calls\n\
1422 8. generator calls\n\
1423 9. All other calls\n\
1424 10. Number of stack pops performed by call_function()"
1425 );
1426 
1427 static PyObject *
sys_callstats(PyObject * self)1428 sys_callstats(PyObject *self)
1429 {
1430     if (PyErr_WarnEx(PyExc_DeprecationWarning,
1431                       "sys.callstats() has been deprecated in Python 3.7 "
1432                       "and will be removed in the future", 1) < 0) {
1433         return NULL;
1434     }
1435 
1436     Py_RETURN_NONE;
1437 }
1438 
1439 
1440 #ifdef __cplusplus
1441 extern "C" {
1442 #endif
1443 
1444 static PyObject *
sys_debugmallocstats(PyObject * self,PyObject * args)1445 sys_debugmallocstats(PyObject *self, PyObject *args)
1446 {
1447 #ifdef WITH_PYMALLOC
1448     if (_PyObject_DebugMallocStats(stderr)) {
1449         fputc('\n', stderr);
1450     }
1451 #endif
1452     _PyObject_DebugTypeStats(stderr);
1453 
1454     Py_RETURN_NONE;
1455 }
1456 PyDoc_STRVAR(debugmallocstats_doc,
1457 "_debugmallocstats()\n\
1458 \n\
1459 Print summary info to stderr about the state of\n\
1460 pymalloc's structures.\n\
1461 \n\
1462 In Py_DEBUG mode, also perform some expensive internal consistency\n\
1463 checks.\n\
1464 ");
1465 
1466 #ifdef Py_TRACE_REFS
1467 /* Defined in objects.c because it uses static globals if that file */
1468 extern PyObject *_Py_GetObjects(PyObject *, PyObject *);
1469 #endif
1470 
1471 #ifdef DYNAMIC_EXECUTION_PROFILE
1472 /* Defined in ceval.c because it uses static globals if that file */
1473 extern PyObject *_Py_GetDXProfile(PyObject *,  PyObject *);
1474 #endif
1475 
1476 #ifdef __cplusplus
1477 }
1478 #endif
1479 
1480 static PyObject *
sys_clear_type_cache(PyObject * self,PyObject * args)1481 sys_clear_type_cache(PyObject* self, PyObject* args)
1482 {
1483     PyType_ClearCache();
1484     Py_RETURN_NONE;
1485 }
1486 
1487 PyDoc_STRVAR(sys_clear_type_cache__doc__,
1488 "_clear_type_cache() -> None\n\
1489 Clear the internal type lookup cache.");
1490 
1491 static PyObject *
sys_is_finalizing(PyObject * self,PyObject * args)1492 sys_is_finalizing(PyObject* self, PyObject* args)
1493 {
1494     return PyBool_FromLong(_Py_IsFinalizing());
1495 }
1496 
1497 PyDoc_STRVAR(is_finalizing_doc,
1498 "is_finalizing()\n\
1499 Return True if Python is exiting.");
1500 
1501 
1502 #ifdef ANDROID_API_LEVEL
1503 PyDoc_STRVAR(getandroidapilevel_doc,
1504 "getandroidapilevel()\n\
1505 \n\
1506 Return the build time API version of Android as an integer.");
1507 
1508 static PyObject *
sys_getandroidapilevel(PyObject * self)1509 sys_getandroidapilevel(PyObject *self)
1510 {
1511     return PyLong_FromLong(ANDROID_API_LEVEL);
1512 }
1513 #endif   /* ANDROID_API_LEVEL */
1514 
1515 
1516 static PyMethodDef sys_methods[] = {
1517     /* Might as well keep this in alphabetic order */
1518     {"breakpointhook",  (PyCFunction)sys_breakpointhook,
1519      METH_FASTCALL | METH_KEYWORDS, breakpointhook_doc},
1520     {"callstats", (PyCFunction)sys_callstats, METH_NOARGS,
1521      callstats_doc},
1522     {"_clear_type_cache",       sys_clear_type_cache,     METH_NOARGS,
1523      sys_clear_type_cache__doc__},
1524     {"_current_frames", sys_current_frames, METH_NOARGS,
1525      current_frames_doc},
1526     {"displayhook",     sys_displayhook, METH_O, displayhook_doc},
1527     {"exc_info",        sys_exc_info, METH_NOARGS, exc_info_doc},
1528     {"excepthook",      sys_excepthook, METH_VARARGS, excepthook_doc},
1529     {"exit",            sys_exit, METH_VARARGS, exit_doc},
1530     {"getdefaultencoding", (PyCFunction)sys_getdefaultencoding,
1531      METH_NOARGS, getdefaultencoding_doc},
1532 #ifdef HAVE_DLOPEN
1533     {"getdlopenflags", (PyCFunction)sys_getdlopenflags, METH_NOARGS,
1534      getdlopenflags_doc},
1535 #endif
1536     {"getallocatedblocks", (PyCFunction)sys_getallocatedblocks, METH_NOARGS,
1537       getallocatedblocks_doc},
1538 #ifdef COUNT_ALLOCS
1539     {"getcounts",       (PyCFunction)sys_getcounts, METH_NOARGS},
1540 #endif
1541 #ifdef DYNAMIC_EXECUTION_PROFILE
1542     {"getdxp",          _Py_GetDXProfile, METH_VARARGS},
1543 #endif
1544     {"getfilesystemencoding", (PyCFunction)sys_getfilesystemencoding,
1545      METH_NOARGS, getfilesystemencoding_doc},
1546     { "getfilesystemencodeerrors", (PyCFunction)sys_getfilesystemencodeerrors,
1547      METH_NOARGS, getfilesystemencodeerrors_doc },
1548 #ifdef Py_TRACE_REFS
1549     {"getobjects",      _Py_GetObjects, METH_VARARGS},
1550 #endif
1551 #ifdef Py_REF_DEBUG
1552     {"gettotalrefcount", (PyCFunction)sys_gettotalrefcount, METH_NOARGS},
1553 #endif
1554     {"getrefcount",     (PyCFunction)sys_getrefcount, METH_O, getrefcount_doc},
1555     {"getrecursionlimit", (PyCFunction)sys_getrecursionlimit, METH_NOARGS,
1556      getrecursionlimit_doc},
1557     {"getsizeof",   (PyCFunction)sys_getsizeof,
1558      METH_VARARGS | METH_KEYWORDS, getsizeof_doc},
1559     {"_getframe", sys_getframe, METH_VARARGS, getframe_doc},
1560 #ifdef MS_WINDOWS
1561     {"getwindowsversion", (PyCFunction)sys_getwindowsversion, METH_NOARGS,
1562      getwindowsversion_doc},
1563     {"_enablelegacywindowsfsencoding", (PyCFunction)sys_enablelegacywindowsfsencoding,
1564      METH_NOARGS, enablelegacywindowsfsencoding_doc },
1565 #endif /* MS_WINDOWS */
1566     {"intern",          sys_intern,     METH_VARARGS, intern_doc},
1567     {"is_finalizing",   sys_is_finalizing, METH_NOARGS, is_finalizing_doc},
1568 #ifdef USE_MALLOPT
1569     {"mdebug",          sys_mdebug, METH_VARARGS},
1570 #endif
1571     {"setcheckinterval",        sys_setcheckinterval, METH_VARARGS,
1572      setcheckinterval_doc},
1573     {"getcheckinterval",        sys_getcheckinterval, METH_NOARGS,
1574      getcheckinterval_doc},
1575     {"setswitchinterval",       sys_setswitchinterval, METH_VARARGS,
1576      setswitchinterval_doc},
1577     {"getswitchinterval",       sys_getswitchinterval, METH_NOARGS,
1578      getswitchinterval_doc},
1579 #ifdef HAVE_DLOPEN
1580     {"setdlopenflags", sys_setdlopenflags, METH_VARARGS,
1581      setdlopenflags_doc},
1582 #endif
1583     {"setprofile",      sys_setprofile, METH_O, setprofile_doc},
1584     {"getprofile",      sys_getprofile, METH_NOARGS, getprofile_doc},
1585     {"setrecursionlimit", sys_setrecursionlimit, METH_VARARGS,
1586      setrecursionlimit_doc},
1587     {"settrace",        sys_settrace, METH_O, settrace_doc},
1588     {"gettrace",        sys_gettrace, METH_NOARGS, gettrace_doc},
1589     {"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
1590     {"_debugmallocstats", sys_debugmallocstats, METH_NOARGS,
1591      debugmallocstats_doc},
1592     SYS_SET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
1593     SYS_GET_COROUTINE_ORIGIN_TRACKING_DEPTH_METHODDEF
1594     {"set_coroutine_wrapper", sys_set_coroutine_wrapper, METH_O,
1595      set_coroutine_wrapper_doc},
1596     {"get_coroutine_wrapper", sys_get_coroutine_wrapper, METH_NOARGS,
1597      get_coroutine_wrapper_doc},
1598     {"set_asyncgen_hooks", (PyCFunction)sys_set_asyncgen_hooks,
1599      METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc},
1600     {"get_asyncgen_hooks", sys_get_asyncgen_hooks, METH_NOARGS,
1601      get_asyncgen_hooks_doc},
1602 #ifdef ANDROID_API_LEVEL
1603     {"getandroidapilevel", (PyCFunction)sys_getandroidapilevel, METH_NOARGS,
1604      getandroidapilevel_doc},
1605 #endif
1606     {NULL,              NULL}           /* sentinel */
1607 };
1608 
1609 static PyObject *
list_builtin_module_names(void)1610 list_builtin_module_names(void)
1611 {
1612     PyObject *list = PyList_New(0);
1613     int i;
1614     if (list == NULL)
1615         return NULL;
1616     for (i = 0; PyImport_Inittab[i].name != NULL; i++) {
1617         PyObject *name = PyUnicode_FromString(
1618             PyImport_Inittab[i].name);
1619         if (name == NULL)
1620             break;
1621         PyList_Append(list, name);
1622         Py_DECREF(name);
1623     }
1624     if (PyList_Sort(list) != 0) {
1625         Py_DECREF(list);
1626         list = NULL;
1627     }
1628     if (list) {
1629         PyObject *v = PyList_AsTuple(list);
1630         Py_DECREF(list);
1631         list = v;
1632     }
1633     return list;
1634 }
1635 
1636 /* Pre-initialization support for sys.warnoptions and sys._xoptions
1637  *
1638  * Modern internal code paths:
1639  *   These APIs get called after _Py_InitializeCore and get to use the
1640  *   regular CPython list, dict, and unicode APIs.
1641  *
1642  * Legacy embedding code paths:
1643  *   The multi-phase initialization API isn't public yet, so embedding
1644  *   apps still need to be able configure sys.warnoptions and sys._xoptions
1645  *   before they call Py_Initialize. To support this, we stash copies of
1646  *   the supplied wchar * sequences in linked lists, and then migrate the
1647  *   contents of those lists to the sys module in _PyInitializeCore.
1648  *
1649  */
1650 
1651 struct _preinit_entry {
1652     wchar_t *value;
1653     struct _preinit_entry *next;
1654 };
1655 
1656 typedef struct _preinit_entry *_Py_PreInitEntry;
1657 
1658 static _Py_PreInitEntry _preinit_warnoptions = NULL;
1659 static _Py_PreInitEntry _preinit_xoptions = NULL;
1660 
1661 static _Py_PreInitEntry
_alloc_preinit_entry(const wchar_t * value)1662 _alloc_preinit_entry(const wchar_t *value)
1663 {
1664     /* To get this to work, we have to initialize the runtime implicitly */
1665     _PyRuntime_Initialize();
1666 
1667     /* Force default allocator, so we can ensure that it also gets used to
1668      * destroy the linked list in _clear_preinit_entries.
1669      */
1670     PyMemAllocatorEx old_alloc;
1671     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1672 
1673     _Py_PreInitEntry node = PyMem_RawCalloc(1, sizeof(*node));
1674     if (node != NULL) {
1675         node->value = _PyMem_RawWcsdup(value);
1676         if (node->value == NULL) {
1677             PyMem_RawFree(node);
1678             node = NULL;
1679         };
1680     };
1681 
1682     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1683     return node;
1684 };
1685 
1686 static int
_append_preinit_entry(_Py_PreInitEntry * optionlist,const wchar_t * value)1687 _append_preinit_entry(_Py_PreInitEntry *optionlist, const wchar_t *value)
1688 {
1689     _Py_PreInitEntry new_entry = _alloc_preinit_entry(value);
1690     if (new_entry == NULL) {
1691         return -1;
1692     }
1693     /* We maintain the linked list in this order so it's easy to play back
1694      * the add commands in the same order later on in _Py_InitializeCore
1695      */
1696     _Py_PreInitEntry last_entry = *optionlist;
1697     if (last_entry == NULL) {
1698         *optionlist = new_entry;
1699     } else {
1700         while (last_entry->next != NULL) {
1701             last_entry = last_entry->next;
1702         }
1703         last_entry->next = new_entry;
1704     }
1705     return 0;
1706 };
1707 
1708 static void
_clear_preinit_entries(_Py_PreInitEntry * optionlist)1709 _clear_preinit_entries(_Py_PreInitEntry *optionlist)
1710 {
1711     _Py_PreInitEntry current = *optionlist;
1712     *optionlist = NULL;
1713     /* Deallocate the nodes and their contents using the default allocator */
1714     PyMemAllocatorEx old_alloc;
1715     _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1716     while (current != NULL) {
1717         _Py_PreInitEntry next = current->next;
1718         PyMem_RawFree(current->value);
1719         PyMem_RawFree(current);
1720         current = next;
1721     }
1722     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
1723 };
1724 
1725 static void
_clear_all_preinit_options(void)1726 _clear_all_preinit_options(void)
1727 {
1728     _clear_preinit_entries(&_preinit_warnoptions);
1729     _clear_preinit_entries(&_preinit_xoptions);
1730 }
1731 
1732 static int
_PySys_ReadPreInitOptions(void)1733 _PySys_ReadPreInitOptions(void)
1734 {
1735     /* Rerun the add commands with the actual sys module available */
1736     PyThreadState *tstate = PyThreadState_GET();
1737     if (tstate == NULL) {
1738         /* Still don't have a thread state, so something is wrong! */
1739         return -1;
1740     }
1741     _Py_PreInitEntry entry = _preinit_warnoptions;
1742     while (entry != NULL) {
1743         PySys_AddWarnOption(entry->value);
1744         entry = entry->next;
1745     }
1746     entry = _preinit_xoptions;
1747     while (entry != NULL) {
1748         PySys_AddXOption(entry->value);
1749         entry = entry->next;
1750     }
1751 
1752     _clear_all_preinit_options();
1753     return 0;
1754 };
1755 
1756 static PyObject *
get_warnoptions(void)1757 get_warnoptions(void)
1758 {
1759     PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
1760     if (warnoptions == NULL || !PyList_Check(warnoptions)) {
1761         /* PEP432 TODO: we can reach this if warnoptions is NULL in the main
1762         *  interpreter config. When that happens, we need to properly set
1763          * the `warnoptions` reference in the main interpreter config as well.
1764          *
1765          * For Python 3.7, we shouldn't be able to get here due to the
1766          * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit
1767          * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig
1768          * call optional for embedding applications, thus making this
1769          * reachable again.
1770          */
1771         warnoptions = PyList_New(0);
1772         if (warnoptions == NULL)
1773             return NULL;
1774         if (_PySys_SetObjectId(&PyId_warnoptions, warnoptions)) {
1775             Py_DECREF(warnoptions);
1776             return NULL;
1777         }
1778         Py_DECREF(warnoptions);
1779     }
1780     return warnoptions;
1781 }
1782 
1783 void
PySys_ResetWarnOptions(void)1784 PySys_ResetWarnOptions(void)
1785 {
1786     PyThreadState *tstate = PyThreadState_GET();
1787     if (tstate == NULL) {
1788         _clear_preinit_entries(&_preinit_warnoptions);
1789         return;
1790     }
1791 
1792     PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
1793     if (warnoptions == NULL || !PyList_Check(warnoptions))
1794         return;
1795     PyList_SetSlice(warnoptions, 0, PyList_GET_SIZE(warnoptions), NULL);
1796 }
1797 
1798 int
_PySys_AddWarnOptionWithError(PyObject * option)1799 _PySys_AddWarnOptionWithError(PyObject *option)
1800 {
1801     PyObject *warnoptions = get_warnoptions();
1802     if (warnoptions == NULL) {
1803         return -1;
1804     }
1805     if (PyList_Append(warnoptions, option)) {
1806         return -1;
1807     }
1808     return 0;
1809 }
1810 
1811 void
PySys_AddWarnOptionUnicode(PyObject * option)1812 PySys_AddWarnOptionUnicode(PyObject *option)
1813 {
1814     (void)_PySys_AddWarnOptionWithError(option);
1815 }
1816 
1817 void
PySys_AddWarnOption(const wchar_t * s)1818 PySys_AddWarnOption(const wchar_t *s)
1819 {
1820     PyThreadState *tstate = PyThreadState_GET();
1821     if (tstate == NULL) {
1822         _append_preinit_entry(&_preinit_warnoptions, s);
1823         return;
1824     }
1825     PyObject *unicode;
1826     unicode = PyUnicode_FromWideChar(s, -1);
1827     if (unicode == NULL)
1828         return;
1829     PySys_AddWarnOptionUnicode(unicode);
1830     Py_DECREF(unicode);
1831 }
1832 
1833 int
PySys_HasWarnOptions(void)1834 PySys_HasWarnOptions(void)
1835 {
1836     PyObject *warnoptions = _PySys_GetObjectId(&PyId_warnoptions);
1837     return (warnoptions != NULL && PyList_Check(warnoptions)
1838             && PyList_GET_SIZE(warnoptions) > 0);
1839 }
1840 
1841 static PyObject *
get_xoptions(void)1842 get_xoptions(void)
1843 {
1844     PyObject *xoptions = _PySys_GetObjectId(&PyId__xoptions);
1845     if (xoptions == NULL || !PyDict_Check(xoptions)) {
1846         /* PEP432 TODO: we can reach this if xoptions is NULL in the main
1847         *  interpreter config. When that happens, we need to properly set
1848          * the `xoptions` reference in the main interpreter config as well.
1849          *
1850          * For Python 3.7, we shouldn't be able to get here due to the
1851          * combination of how _PyMainInterpreter_ReadConfig and _PySys_EndInit
1852          * work, but we expect 3.8+ to make the _PyMainInterpreter_ReadConfig
1853          * call optional for embedding applications, thus making this
1854          * reachable again.
1855          */
1856         xoptions = PyDict_New();
1857         if (xoptions == NULL)
1858             return NULL;
1859         if (_PySys_SetObjectId(&PyId__xoptions, xoptions)) {
1860             Py_DECREF(xoptions);
1861             return NULL;
1862         }
1863         Py_DECREF(xoptions);
1864     }
1865     return xoptions;
1866 }
1867 
1868 int
_PySys_AddXOptionWithError(const wchar_t * s)1869 _PySys_AddXOptionWithError(const wchar_t *s)
1870 {
1871     PyObject *name = NULL, *value = NULL;
1872 
1873     PyObject *opts = get_xoptions();
1874     if (opts == NULL) {
1875         goto error;
1876     }
1877 
1878     const wchar_t *name_end = wcschr(s, L'=');
1879     if (!name_end) {
1880         name = PyUnicode_FromWideChar(s, -1);
1881         value = Py_True;
1882         Py_INCREF(value);
1883     }
1884     else {
1885         name = PyUnicode_FromWideChar(s, name_end - s);
1886         value = PyUnicode_FromWideChar(name_end + 1, -1);
1887     }
1888     if (name == NULL || value == NULL) {
1889         goto error;
1890     }
1891     if (PyDict_SetItem(opts, name, value) < 0) {
1892         goto error;
1893     }
1894     Py_DECREF(name);
1895     Py_DECREF(value);
1896     return 0;
1897 
1898 error:
1899     Py_XDECREF(name);
1900     Py_XDECREF(value);
1901     return -1;
1902 }
1903 
1904 void
PySys_AddXOption(const wchar_t * s)1905 PySys_AddXOption(const wchar_t *s)
1906 {
1907     PyThreadState *tstate = PyThreadState_GET();
1908     if (tstate == NULL) {
1909         _append_preinit_entry(&_preinit_xoptions, s);
1910         return;
1911     }
1912     if (_PySys_AddXOptionWithError(s) < 0) {
1913         /* No return value, therefore clear error state if possible */
1914         if (_PyThreadState_UncheckedGet()) {
1915             PyErr_Clear();
1916         }
1917     }
1918 }
1919 
1920 PyObject *
PySys_GetXOptions(void)1921 PySys_GetXOptions(void)
1922 {
1923     return get_xoptions();
1924 }
1925 
1926 /* XXX This doc string is too long to be a single string literal in VC++ 5.0.
1927    Two literals concatenated works just fine.  If you have a K&R compiler
1928    or other abomination that however *does* understand longer strings,
1929    get rid of the !!! comment in the middle and the quotes that surround it. */
1930 PyDoc_VAR(sys_doc) =
1931 PyDoc_STR(
1932 "This module provides access to some objects used or maintained by the\n\
1933 interpreter and to functions that interact strongly with the interpreter.\n\
1934 \n\
1935 Dynamic objects:\n\
1936 \n\
1937 argv -- command line arguments; argv[0] is the script pathname if known\n\
1938 path -- module search path; path[0] is the script directory, else ''\n\
1939 modules -- dictionary of loaded modules\n\
1940 \n\
1941 displayhook -- called to show results in an interactive session\n\
1942 excepthook -- called to handle any uncaught exception other than SystemExit\n\
1943   To customize printing in an interactive session or to install a custom\n\
1944   top-level exception handler, assign other functions to replace these.\n\
1945 \n\
1946 stdin -- standard input file object; used by input()\n\
1947 stdout -- standard output file object; used by print()\n\
1948 stderr -- standard error object; used for error messages\n\
1949   By assigning other file objects (or objects that behave like files)\n\
1950   to these, it is possible to redirect all of the interpreter's I/O.\n\
1951 \n\
1952 last_type -- type of last uncaught exception\n\
1953 last_value -- value of last uncaught exception\n\
1954 last_traceback -- traceback of last uncaught exception\n\
1955   These three are only available in an interactive session after a\n\
1956   traceback has been printed.\n\
1957 "
1958 )
1959 /* concatenating string here */
1960 PyDoc_STR(
1961 "\n\
1962 Static objects:\n\
1963 \n\
1964 builtin_module_names -- tuple of module names built into this interpreter\n\
1965 copyright -- copyright notice pertaining to this interpreter\n\
1966 exec_prefix -- prefix used to find the machine-specific Python library\n\
1967 executable -- absolute path of the executable binary of the Python interpreter\n\
1968 float_info -- a struct sequence with information about the float implementation.\n\
1969 float_repr_style -- string indicating the style of repr() output for floats\n\
1970 hash_info -- a struct sequence with information about the hash algorithm.\n\
1971 hexversion -- version information encoded as a single integer\n\
1972 implementation -- Python implementation information.\n\
1973 int_info -- a struct sequence with information about the int implementation.\n\
1974 maxsize -- the largest supported length of containers.\n\
1975 maxunicode -- the value of the largest Unicode code point\n\
1976 platform -- platform identifier\n\
1977 prefix -- prefix used to find the Python library\n\
1978 thread_info -- a struct sequence with information about the thread implementation.\n\
1979 version -- the version of this interpreter as a string\n\
1980 version_info -- version information as a named tuple\n\
1981 "
1982 )
1983 #ifdef MS_COREDLL
1984 /* concatenating string here */
1985 PyDoc_STR(
1986 "dllhandle -- [Windows only] integer handle of the Python DLL\n\
1987 winver -- [Windows only] version number of the Python DLL\n\
1988 "
1989 )
1990 #endif /* MS_COREDLL */
1991 #ifdef MS_WINDOWS
1992 /* concatenating string here */
1993 PyDoc_STR(
1994 "_enablelegacywindowsfsencoding -- [Windows only] \n\
1995 "
1996 )
1997 #endif
1998 PyDoc_STR(
1999 "__stdin__ -- the original stdin; don't touch!\n\
2000 __stdout__ -- the original stdout; don't touch!\n\
2001 __stderr__ -- the original stderr; don't touch!\n\
2002 __displayhook__ -- the original displayhook; don't touch!\n\
2003 __excepthook__ -- the original excepthook; don't touch!\n\
2004 \n\
2005 Functions:\n\
2006 \n\
2007 displayhook() -- print an object to the screen, and save it in builtins._\n\
2008 excepthook() -- print an exception and its traceback to sys.stderr\n\
2009 exc_info() -- return thread-safe information about the current exception\n\
2010 exit() -- exit the interpreter by raising SystemExit\n\
2011 getdlopenflags() -- returns flags to be used for dlopen() calls\n\
2012 getprofile() -- get the global profiling function\n\
2013 getrefcount() -- return the reference count for an object (plus one :-)\n\
2014 getrecursionlimit() -- return the max recursion depth for the interpreter\n\
2015 getsizeof() -- return the size of an object in bytes\n\
2016 gettrace() -- get the global debug tracing function\n\
2017 setcheckinterval() -- control how often the interpreter checks for events\n\
2018 setdlopenflags() -- set the flags to be used for dlopen() calls\n\
2019 setprofile() -- set the global profiling function\n\
2020 setrecursionlimit() -- set the max recursion depth for the interpreter\n\
2021 settrace() -- set the global debug tracing function\n\
2022 "
2023 )
2024 /* end of sys_doc */ ;
2025 
2026 
2027 PyDoc_STRVAR(flags__doc__,
2028 "sys.flags\n\
2029 \n\
2030 Flags provided through command line arguments or environment vars.");
2031 
2032 static PyTypeObject FlagsType;
2033 
2034 static PyStructSequence_Field flags_fields[] = {
2035     {"debug",                   "-d"},
2036     {"inspect",                 "-i"},
2037     {"interactive",             "-i"},
2038     {"optimize",                "-O or -OO"},
2039     {"dont_write_bytecode",     "-B"},
2040     {"no_user_site",            "-s"},
2041     {"no_site",                 "-S"},
2042     {"ignore_environment",      "-E"},
2043     {"verbose",                 "-v"},
2044     /* {"unbuffered",                   "-u"}, */
2045     /* {"skip_first",                   "-x"}, */
2046     {"bytes_warning",           "-b"},
2047     {"quiet",                   "-q"},
2048     {"hash_randomization",      "-R"},
2049     {"isolated",                "-I"},
2050     {"dev_mode",                "-X dev"},
2051     {"utf8_mode",               "-X utf8"},
2052     {0}
2053 };
2054 
2055 static PyStructSequence_Desc flags_desc = {
2056     "sys.flags",        /* name */
2057     flags__doc__,       /* doc */
2058     flags_fields,       /* fields */
2059     15
2060 };
2061 
2062 static PyObject*
make_flags(void)2063 make_flags(void)
2064 {
2065     int pos = 0;
2066     PyObject *seq;
2067     _PyCoreConfig *core_config = &_PyGILState_GetInterpreterStateUnsafe()->core_config;
2068 
2069     seq = PyStructSequence_New(&FlagsType);
2070     if (seq == NULL)
2071         return NULL;
2072 
2073 #define SetFlag(flag) \
2074     PyStructSequence_SET_ITEM(seq, pos++, PyLong_FromLong(flag))
2075 
2076     SetFlag(Py_DebugFlag);
2077     SetFlag(Py_InspectFlag);
2078     SetFlag(Py_InteractiveFlag);
2079     SetFlag(Py_OptimizeFlag);
2080     SetFlag(Py_DontWriteBytecodeFlag);
2081     SetFlag(Py_NoUserSiteDirectory);
2082     SetFlag(Py_NoSiteFlag);
2083     SetFlag(Py_IgnoreEnvironmentFlag);
2084     SetFlag(Py_VerboseFlag);
2085     /* SetFlag(saw_unbuffered_flag); */
2086     /* SetFlag(skipfirstline); */
2087     SetFlag(Py_BytesWarningFlag);
2088     SetFlag(Py_QuietFlag);
2089     SetFlag(Py_HashRandomizationFlag);
2090     SetFlag(Py_IsolatedFlag);
2091     PyStructSequence_SET_ITEM(seq, pos++, PyBool_FromLong(core_config->dev_mode));
2092     SetFlag(Py_UTF8Mode);
2093 #undef SetFlag
2094 
2095     if (PyErr_Occurred()) {
2096         Py_DECREF(seq);
2097         return NULL;
2098     }
2099     return seq;
2100 }
2101 
2102 PyDoc_STRVAR(version_info__doc__,
2103 "sys.version_info\n\
2104 \n\
2105 Version information as a named tuple.");
2106 
2107 static PyTypeObject VersionInfoType;
2108 
2109 static PyStructSequence_Field version_info_fields[] = {
2110     {"major", "Major release number"},
2111     {"minor", "Minor release number"},
2112     {"micro", "Patch release number"},
2113     {"releaselevel", "'alpha', 'beta', 'candidate', or 'final'"},
2114     {"serial", "Serial release number"},
2115     {0}
2116 };
2117 
2118 static PyStructSequence_Desc version_info_desc = {
2119     "sys.version_info",     /* name */
2120     version_info__doc__,    /* doc */
2121     version_info_fields,    /* fields */
2122     5
2123 };
2124 
2125 static PyObject *
make_version_info(void)2126 make_version_info(void)
2127 {
2128     PyObject *version_info;
2129     char *s;
2130     int pos = 0;
2131 
2132     version_info = PyStructSequence_New(&VersionInfoType);
2133     if (version_info == NULL) {
2134         return NULL;
2135     }
2136 
2137     /*
2138      * These release level checks are mutually exclusive and cover
2139      * the field, so don't get too fancy with the pre-processor!
2140      */
2141 #if PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_ALPHA
2142     s = "alpha";
2143 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_BETA
2144     s = "beta";
2145 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_GAMMA
2146     s = "candidate";
2147 #elif PY_RELEASE_LEVEL == PY_RELEASE_LEVEL_FINAL
2148     s = "final";
2149 #endif
2150 
2151 #define SetIntItem(flag) \
2152     PyStructSequence_SET_ITEM(version_info, pos++, PyLong_FromLong(flag))
2153 #define SetStrItem(flag) \
2154     PyStructSequence_SET_ITEM(version_info, pos++, PyUnicode_FromString(flag))
2155 
2156     SetIntItem(PY_MAJOR_VERSION);
2157     SetIntItem(PY_MINOR_VERSION);
2158     SetIntItem(PY_MICRO_VERSION);
2159     SetStrItem(s);
2160     SetIntItem(PY_RELEASE_SERIAL);
2161 #undef SetIntItem
2162 #undef SetStrItem
2163 
2164     if (PyErr_Occurred()) {
2165         Py_CLEAR(version_info);
2166         return NULL;
2167     }
2168     return version_info;
2169 }
2170 
2171 /* sys.implementation values */
2172 #define NAME "cpython"
2173 const char *_PySys_ImplName = NAME;
2174 #define MAJOR Py_STRINGIFY(PY_MAJOR_VERSION)
2175 #define MINOR Py_STRINGIFY(PY_MINOR_VERSION)
2176 #define TAG NAME "-" MAJOR MINOR
2177 const char *_PySys_ImplCacheTag = TAG;
2178 #undef NAME
2179 #undef MAJOR
2180 #undef MINOR
2181 #undef TAG
2182 
2183 static PyObject *
make_impl_info(PyObject * version_info)2184 make_impl_info(PyObject *version_info)
2185 {
2186     int res;
2187     PyObject *impl_info, *value, *ns;
2188 
2189     impl_info = PyDict_New();
2190     if (impl_info == NULL)
2191         return NULL;
2192 
2193     /* populate the dict */
2194 
2195     value = PyUnicode_FromString(_PySys_ImplName);
2196     if (value == NULL)
2197         goto error;
2198     res = PyDict_SetItemString(impl_info, "name", value);
2199     Py_DECREF(value);
2200     if (res < 0)
2201         goto error;
2202 
2203     value = PyUnicode_FromString(_PySys_ImplCacheTag);
2204     if (value == NULL)
2205         goto error;
2206     res = PyDict_SetItemString(impl_info, "cache_tag", value);
2207     Py_DECREF(value);
2208     if (res < 0)
2209         goto error;
2210 
2211     res = PyDict_SetItemString(impl_info, "version", version_info);
2212     if (res < 0)
2213         goto error;
2214 
2215     value = PyLong_FromLong(PY_VERSION_HEX);
2216     if (value == NULL)
2217         goto error;
2218     res = PyDict_SetItemString(impl_info, "hexversion", value);
2219     Py_DECREF(value);
2220     if (res < 0)
2221         goto error;
2222 
2223 #ifdef MULTIARCH
2224     value = PyUnicode_FromString(MULTIARCH);
2225     if (value == NULL)
2226         goto error;
2227     res = PyDict_SetItemString(impl_info, "_multiarch", value);
2228     Py_DECREF(value);
2229     if (res < 0)
2230         goto error;
2231 #endif
2232 
2233     /* dict ready */
2234 
2235     ns = _PyNamespace_New(impl_info);
2236     Py_DECREF(impl_info);
2237     return ns;
2238 
2239 error:
2240     Py_CLEAR(impl_info);
2241     return NULL;
2242 }
2243 
2244 static struct PyModuleDef sysmodule = {
2245     PyModuleDef_HEAD_INIT,
2246     "sys",
2247     sys_doc,
2248     -1, /* multiple "initialization" just copies the module dict. */
2249     sys_methods,
2250     NULL,
2251     NULL,
2252     NULL,
2253     NULL
2254 };
2255 
2256 /* Updating the sys namespace, returning NULL pointer on error */
2257 #define SET_SYS_FROM_STRING_BORROW(key, value)             \
2258     do {                                                   \
2259         PyObject *v = (value);                             \
2260         if (v == NULL) {                                   \
2261             goto err_occurred;                             \
2262         }                                                  \
2263         res = PyDict_SetItemString(sysdict, key, v);       \
2264         if (res < 0) {                                     \
2265             goto err_occurred;                             \
2266         }                                                  \
2267     } while (0)
2268 #define SET_SYS_FROM_STRING(key, value)                    \
2269     do {                                                   \
2270         PyObject *v = (value);                             \
2271         if (v == NULL) {                                   \
2272             goto err_occurred;                             \
2273         }                                                  \
2274         res = PyDict_SetItemString(sysdict, key, v);       \
2275         Py_DECREF(v);                                      \
2276         if (res < 0) {                                     \
2277             goto err_occurred;                             \
2278         }                                                  \
2279     } while (0)
2280 
2281 
2282 _PyInitError
_PySys_BeginInit(PyObject ** sysmod)2283 _PySys_BeginInit(PyObject **sysmod)
2284 {
2285     PyObject *m, *sysdict, *version_info;
2286     int res;
2287 
2288     m = _PyModule_CreateInitialized(&sysmodule, PYTHON_API_VERSION);
2289     if (m == NULL) {
2290         return _Py_INIT_ERR("failed to create a module object");
2291     }
2292     sysdict = PyModule_GetDict(m);
2293 
2294     /* Check that stdin is not a directory
2295        Using shell redirection, you can redirect stdin to a directory,
2296        crashing the Python interpreter. Catch this common mistake here
2297        and output a useful error message. Note that under MS Windows,
2298        the shell already prevents that. */
2299 #ifndef MS_WINDOWS
2300     {
2301         struct _Py_stat_struct sb;
2302         if (_Py_fstat_noraise(fileno(stdin), &sb) == 0 &&
2303             S_ISDIR(sb.st_mode)) {
2304             return _Py_INIT_USER_ERR("<stdin> is a directory, "
2305                                      "cannot continue");
2306         }
2307     }
2308 #endif
2309 
2310     /* stdin/stdout/stderr are set in pylifecycle.c */
2311 
2312     SET_SYS_FROM_STRING_BORROW("__displayhook__",
2313                                PyDict_GetItemString(sysdict, "displayhook"));
2314     SET_SYS_FROM_STRING_BORROW("__excepthook__",
2315                                PyDict_GetItemString(sysdict, "excepthook"));
2316     SET_SYS_FROM_STRING_BORROW(
2317         "__breakpointhook__",
2318         PyDict_GetItemString(sysdict, "breakpointhook"));
2319     SET_SYS_FROM_STRING("version",
2320                          PyUnicode_FromString(Py_GetVersion()));
2321     SET_SYS_FROM_STRING("hexversion",
2322                          PyLong_FromLong(PY_VERSION_HEX));
2323     SET_SYS_FROM_STRING("_git",
2324                         Py_BuildValue("(szz)", "CPython", _Py_gitidentifier(),
2325                                       _Py_gitversion()));
2326     SET_SYS_FROM_STRING("_framework", PyUnicode_FromString(_PYTHONFRAMEWORK));
2327     SET_SYS_FROM_STRING("api_version",
2328                         PyLong_FromLong(PYTHON_API_VERSION));
2329     SET_SYS_FROM_STRING("copyright",
2330                         PyUnicode_FromString(Py_GetCopyright()));
2331     SET_SYS_FROM_STRING("platform",
2332                         PyUnicode_FromString(Py_GetPlatform()));
2333     SET_SYS_FROM_STRING("maxsize",
2334                         PyLong_FromSsize_t(PY_SSIZE_T_MAX));
2335     SET_SYS_FROM_STRING("float_info",
2336                         PyFloat_GetInfo());
2337     SET_SYS_FROM_STRING("int_info",
2338                         PyLong_GetInfo());
2339     /* initialize hash_info */
2340     if (Hash_InfoType.tp_name == NULL) {
2341         if (PyStructSequence_InitType2(&Hash_InfoType, &hash_info_desc) < 0) {
2342             goto type_init_failed;
2343         }
2344     }
2345     SET_SYS_FROM_STRING("hash_info",
2346                         get_hash_info());
2347     SET_SYS_FROM_STRING("maxunicode",
2348                         PyLong_FromLong(0x10FFFF));
2349     SET_SYS_FROM_STRING("builtin_module_names",
2350                         list_builtin_module_names());
2351 #if PY_BIG_ENDIAN
2352     SET_SYS_FROM_STRING("byteorder",
2353                         PyUnicode_FromString("big"));
2354 #else
2355     SET_SYS_FROM_STRING("byteorder",
2356                         PyUnicode_FromString("little"));
2357 #endif
2358 
2359 #ifdef MS_COREDLL
2360     SET_SYS_FROM_STRING("dllhandle",
2361                         PyLong_FromVoidPtr(PyWin_DLLhModule));
2362     SET_SYS_FROM_STRING("winver",
2363                         PyUnicode_FromString(PyWin_DLLVersionString));
2364 #endif
2365 #ifdef ABIFLAGS
2366     SET_SYS_FROM_STRING("abiflags",
2367                         PyUnicode_FromString(ABIFLAGS));
2368 #endif
2369 
2370     /* version_info */
2371     if (VersionInfoType.tp_name == NULL) {
2372         if (PyStructSequence_InitType2(&VersionInfoType,
2373                                        &version_info_desc) < 0) {
2374             goto type_init_failed;
2375         }
2376     }
2377     version_info = make_version_info();
2378     SET_SYS_FROM_STRING("version_info", version_info);
2379     /* prevent user from creating new instances */
2380     VersionInfoType.tp_init = NULL;
2381     VersionInfoType.tp_new = NULL;
2382     res = PyDict_DelItemString(VersionInfoType.tp_dict, "__new__");
2383     if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError))
2384         PyErr_Clear();
2385 
2386     /* implementation */
2387     SET_SYS_FROM_STRING("implementation", make_impl_info(version_info));
2388 
2389     /* flags */
2390     if (FlagsType.tp_name == 0) {
2391         if (PyStructSequence_InitType2(&FlagsType, &flags_desc) < 0) {
2392             goto type_init_failed;
2393         }
2394     }
2395     /* Set flags to their default values */
2396     SET_SYS_FROM_STRING("flags", make_flags());
2397 
2398 #if defined(MS_WINDOWS)
2399     /* getwindowsversion */
2400     if (WindowsVersionType.tp_name == 0)
2401         if (PyStructSequence_InitType2(&WindowsVersionType,
2402                                        &windows_version_desc) < 0) {
2403             goto type_init_failed;
2404         }
2405     /* prevent user from creating new instances */
2406     WindowsVersionType.tp_init = NULL;
2407     WindowsVersionType.tp_new = NULL;
2408     assert(!PyErr_Occurred());
2409     res = PyDict_DelItemString(WindowsVersionType.tp_dict, "__new__");
2410     if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) {
2411         PyErr_Clear();
2412     }
2413 #endif
2414 
2415     /* float repr style: 0.03 (short) vs 0.029999999999999999 (legacy) */
2416 #ifndef PY_NO_SHORT_FLOAT_REPR
2417     SET_SYS_FROM_STRING("float_repr_style",
2418                         PyUnicode_FromString("short"));
2419 #else
2420     SET_SYS_FROM_STRING("float_repr_style",
2421                         PyUnicode_FromString("legacy"));
2422 #endif
2423 
2424     SET_SYS_FROM_STRING("thread_info", PyThread_GetInfo());
2425 
2426     /* initialize asyncgen_hooks */
2427     if (AsyncGenHooksType.tp_name == NULL) {
2428         if (PyStructSequence_InitType2(
2429                 &AsyncGenHooksType, &asyncgen_hooks_desc) < 0) {
2430             goto type_init_failed;
2431         }
2432     }
2433 
2434     if (PyErr_Occurred()) {
2435         goto err_occurred;
2436     }
2437 
2438     *sysmod = m;
2439 
2440     return _Py_INIT_OK();
2441 
2442 type_init_failed:
2443     return _Py_INIT_ERR("failed to initialize a type");
2444 
2445 err_occurred:
2446     return _Py_INIT_ERR("can't initialize sys module");
2447 }
2448 
2449 #undef SET_SYS_FROM_STRING
2450 
2451 /* Updating the sys namespace, returning integer error codes */
2452 #define SET_SYS_FROM_STRING_INT_RESULT(key, value)         \
2453     do {                                                   \
2454         PyObject *v = (value);                             \
2455         if (v == NULL)                                     \
2456             return -1;                                     \
2457         res = PyDict_SetItemString(sysdict, key, v);       \
2458         Py_DECREF(v);                                      \
2459         if (res < 0) {                                     \
2460             return res;                                    \
2461         }                                                  \
2462     } while (0)
2463 
2464 int
_PySys_EndInit(PyObject * sysdict,_PyMainInterpreterConfig * config)2465 _PySys_EndInit(PyObject *sysdict, _PyMainInterpreterConfig *config)
2466 {
2467     int res;
2468 
2469     /* _PyMainInterpreterConfig_Read() must set all these variables */
2470     assert(config->module_search_path != NULL);
2471     assert(config->executable != NULL);
2472     assert(config->prefix != NULL);
2473     assert(config->base_prefix != NULL);
2474     assert(config->exec_prefix != NULL);
2475     assert(config->base_exec_prefix != NULL);
2476 
2477     SET_SYS_FROM_STRING_BORROW("path", config->module_search_path);
2478     SET_SYS_FROM_STRING_BORROW("executable", config->executable);
2479     SET_SYS_FROM_STRING_BORROW("prefix", config->prefix);
2480     SET_SYS_FROM_STRING_BORROW("base_prefix", config->base_prefix);
2481     SET_SYS_FROM_STRING_BORROW("exec_prefix", config->exec_prefix);
2482     SET_SYS_FROM_STRING_BORROW("base_exec_prefix", config->base_exec_prefix);
2483 
2484     if (config->argv != NULL) {
2485         SET_SYS_FROM_STRING_BORROW("argv", config->argv);
2486     }
2487     if (config->warnoptions != NULL) {
2488         SET_SYS_FROM_STRING_BORROW("warnoptions", config->warnoptions);
2489     }
2490     if (config->xoptions != NULL) {
2491         SET_SYS_FROM_STRING_BORROW("_xoptions", config->xoptions);
2492     }
2493 
2494     /* Set flags to their final values */
2495     SET_SYS_FROM_STRING_INT_RESULT("flags", make_flags());
2496     /* prevent user from creating new instances */
2497     FlagsType.tp_init = NULL;
2498     FlagsType.tp_new = NULL;
2499     res = PyDict_DelItemString(FlagsType.tp_dict, "__new__");
2500     if (res < 0) {
2501         if (!PyErr_ExceptionMatches(PyExc_KeyError)) {
2502             return res;
2503         }
2504         PyErr_Clear();
2505     }
2506 
2507     SET_SYS_FROM_STRING_INT_RESULT("dont_write_bytecode",
2508                          PyBool_FromLong(Py_DontWriteBytecodeFlag));
2509 
2510     if (get_warnoptions() == NULL)
2511         return -1;
2512 
2513     if (get_xoptions() == NULL)
2514         return -1;
2515 
2516     /* Transfer any sys.warnoptions and sys._xoptions set directly
2517      * by an embedding application from the linked list to the module. */
2518     if (_PySys_ReadPreInitOptions() != 0)
2519         return -1;
2520 
2521     if (PyErr_Occurred())
2522         return -1;
2523     return 0;
2524 
2525 err_occurred:
2526     return -1;
2527 }
2528 
2529 #undef SET_SYS_FROM_STRING_BORROW
2530 #undef SET_SYS_FROM_STRING_INT_RESULT
2531 
2532 static PyObject *
makepathobject(const wchar_t * path,wchar_t delim)2533 makepathobject(const wchar_t *path, wchar_t delim)
2534 {
2535     int i, n;
2536     const wchar_t *p;
2537     PyObject *v, *w;
2538 
2539     n = 1;
2540     p = path;
2541     while ((p = wcschr(p, delim)) != NULL) {
2542         n++;
2543         p++;
2544     }
2545     v = PyList_New(n);
2546     if (v == NULL)
2547         return NULL;
2548     for (i = 0; ; i++) {
2549         p = wcschr(path, delim);
2550         if (p == NULL)
2551             p = path + wcslen(path); /* End of string */
2552         w = PyUnicode_FromWideChar(path, (Py_ssize_t)(p - path));
2553         if (w == NULL) {
2554             Py_DECREF(v);
2555             return NULL;
2556         }
2557         PyList_SET_ITEM(v, i, w);
2558         if (*p == '\0')
2559             break;
2560         path = p+1;
2561     }
2562     return v;
2563 }
2564 
2565 void
PySys_SetPath(const wchar_t * path)2566 PySys_SetPath(const wchar_t *path)
2567 {
2568     PyObject *v;
2569     if ((v = makepathobject(path, DELIM)) == NULL)
2570         Py_FatalError("can't create sys.path");
2571     if (_PySys_SetObjectId(&PyId_path, v) != 0)
2572         Py_FatalError("can't assign sys.path");
2573     Py_DECREF(v);
2574 }
2575 
2576 static PyObject *
makeargvobject(int argc,wchar_t ** argv)2577 makeargvobject(int argc, wchar_t **argv)
2578 {
2579     PyObject *av;
2580     if (argc <= 0 || argv == NULL) {
2581         /* Ensure at least one (empty) argument is seen */
2582         static wchar_t *empty_argv[1] = {L""};
2583         argv = empty_argv;
2584         argc = 1;
2585     }
2586     av = PyList_New(argc);
2587     if (av != NULL) {
2588         int i;
2589         for (i = 0; i < argc; i++) {
2590             PyObject *v = PyUnicode_FromWideChar(argv[i], -1);
2591             if (v == NULL) {
2592                 Py_DECREF(av);
2593                 av = NULL;
2594                 break;
2595             }
2596             PyList_SET_ITEM(av, i, v);
2597         }
2598     }
2599     return av;
2600 }
2601 
2602 void
PySys_SetArgvEx(int argc,wchar_t ** argv,int updatepath)2603 PySys_SetArgvEx(int argc, wchar_t **argv, int updatepath)
2604 {
2605     PyObject *av = makeargvobject(argc, argv);
2606     if (av == NULL) {
2607         Py_FatalError("no mem for sys.argv");
2608     }
2609     if (PySys_SetObject("argv", av) != 0) {
2610         Py_DECREF(av);
2611         Py_FatalError("can't assign sys.argv");
2612     }
2613     Py_DECREF(av);
2614 
2615     if (updatepath) {
2616         /* If argv[0] is not '-c' nor '-m', prepend argv[0] to sys.path.
2617            If argv[0] is a symlink, use the real path. */
2618         PyObject *argv0 = _PyPathConfig_ComputeArgv0(argc, argv);
2619         if (argv0 == NULL) {
2620             Py_FatalError("can't compute path0 from argv");
2621         }
2622 
2623         PyObject *sys_path = _PySys_GetObjectId(&PyId_path);
2624         if (sys_path != NULL) {
2625             if (PyList_Insert(sys_path, 0, argv0) < 0) {
2626                 Py_DECREF(argv0);
2627                 Py_FatalError("can't prepend path0 to sys.path");
2628             }
2629         }
2630         Py_DECREF(argv0);
2631     }
2632 }
2633 
2634 void
PySys_SetArgv(int argc,wchar_t ** argv)2635 PySys_SetArgv(int argc, wchar_t **argv)
2636 {
2637     PySys_SetArgvEx(argc, argv, Py_IsolatedFlag == 0);
2638 }
2639 
2640 /* Reimplementation of PyFile_WriteString() no calling indirectly
2641    PyErr_CheckSignals(): avoid the call to PyObject_Str(). */
2642 
2643 static int
sys_pyfile_write_unicode(PyObject * unicode,PyObject * file)2644 sys_pyfile_write_unicode(PyObject *unicode, PyObject *file)
2645 {
2646     PyObject *writer = NULL, *result = NULL;
2647     int err;
2648 
2649     if (file == NULL)
2650         return -1;
2651 
2652     writer = _PyObject_GetAttrId(file, &PyId_write);
2653     if (writer == NULL)
2654         goto error;
2655 
2656     result = PyObject_CallFunctionObjArgs(writer, unicode, NULL);
2657     if (result == NULL) {
2658         goto error;
2659     } else {
2660         err = 0;
2661         goto finally;
2662     }
2663 
2664 error:
2665     err = -1;
2666 finally:
2667     Py_XDECREF(writer);
2668     Py_XDECREF(result);
2669     return err;
2670 }
2671 
2672 static int
sys_pyfile_write(const char * text,PyObject * file)2673 sys_pyfile_write(const char *text, PyObject *file)
2674 {
2675     PyObject *unicode = NULL;
2676     int err;
2677 
2678     if (file == NULL)
2679         return -1;
2680 
2681     unicode = PyUnicode_FromString(text);
2682     if (unicode == NULL)
2683         return -1;
2684 
2685     err = sys_pyfile_write_unicode(unicode, file);
2686     Py_DECREF(unicode);
2687     return err;
2688 }
2689 
2690 /* APIs to write to sys.stdout or sys.stderr using a printf-like interface.
2691    Adapted from code submitted by Just van Rossum.
2692 
2693    PySys_WriteStdout(format, ...)
2694    PySys_WriteStderr(format, ...)
2695 
2696       The first function writes to sys.stdout; the second to sys.stderr.  When
2697       there is a problem, they write to the real (C level) stdout or stderr;
2698       no exceptions are raised.
2699 
2700       PyErr_CheckSignals() is not called to avoid the execution of the Python
2701       signal handlers: they may raise a new exception whereas sys_write()
2702       ignores all exceptions.
2703 
2704       Both take a printf-style format string as their first argument followed
2705       by a variable length argument list determined by the format string.
2706 
2707       *** WARNING ***
2708 
2709       The format should limit the total size of the formatted output string to
2710       1000 bytes.  In particular, this means that no unrestricted "%s" formats
2711       should occur; these should be limited using "%.<N>s where <N> is a
2712       decimal number calculated so that <N> plus the maximum size of other
2713       formatted text does not exceed 1000 bytes.  Also watch out for "%f",
2714       which can print hundreds of digits for very large numbers.
2715 
2716  */
2717 
2718 static void
sys_write(_Py_Identifier * key,FILE * fp,const char * format,va_list va)2719 sys_write(_Py_Identifier *key, FILE *fp, const char *format, va_list va)
2720 {
2721     PyObject *file;
2722     PyObject *error_type, *error_value, *error_traceback;
2723     char buffer[1001];
2724     int written;
2725 
2726     PyErr_Fetch(&error_type, &error_value, &error_traceback);
2727     file = _PySys_GetObjectId(key);
2728     written = PyOS_vsnprintf(buffer, sizeof(buffer), format, va);
2729     if (sys_pyfile_write(buffer, file) != 0) {
2730         PyErr_Clear();
2731         fputs(buffer, fp);
2732     }
2733     if (written < 0 || (size_t)written >= sizeof(buffer)) {
2734         const char *truncated = "... truncated";
2735         if (sys_pyfile_write(truncated, file) != 0)
2736             fputs(truncated, fp);
2737     }
2738     PyErr_Restore(error_type, error_value, error_traceback);
2739 }
2740 
2741 void
PySys_WriteStdout(const char * format,...)2742 PySys_WriteStdout(const char *format, ...)
2743 {
2744     va_list va;
2745 
2746     va_start(va, format);
2747     sys_write(&PyId_stdout, stdout, format, va);
2748     va_end(va);
2749 }
2750 
2751 void
PySys_WriteStderr(const char * format,...)2752 PySys_WriteStderr(const char *format, ...)
2753 {
2754     va_list va;
2755 
2756     va_start(va, format);
2757     sys_write(&PyId_stderr, stderr, format, va);
2758     va_end(va);
2759 }
2760 
2761 static void
sys_format(_Py_Identifier * key,FILE * fp,const char * format,va_list va)2762 sys_format(_Py_Identifier *key, FILE *fp, const char *format, va_list va)
2763 {
2764     PyObject *file, *message;
2765     PyObject *error_type, *error_value, *error_traceback;
2766     const char *utf8;
2767 
2768     PyErr_Fetch(&error_type, &error_value, &error_traceback);
2769     file = _PySys_GetObjectId(key);
2770     message = PyUnicode_FromFormatV(format, va);
2771     if (message != NULL) {
2772         if (sys_pyfile_write_unicode(message, file) != 0) {
2773             PyErr_Clear();
2774             utf8 = PyUnicode_AsUTF8(message);
2775             if (utf8 != NULL)
2776                 fputs(utf8, fp);
2777         }
2778         Py_DECREF(message);
2779     }
2780     PyErr_Restore(error_type, error_value, error_traceback);
2781 }
2782 
2783 void
PySys_FormatStdout(const char * format,...)2784 PySys_FormatStdout(const char *format, ...)
2785 {
2786     va_list va;
2787 
2788     va_start(va, format);
2789     sys_format(&PyId_stdout, stdout, format, va);
2790     va_end(va);
2791 }
2792 
2793 void
PySys_FormatStderr(const char * format,...)2794 PySys_FormatStderr(const char *format, ...)
2795 {
2796     va_list va;
2797 
2798     va_start(va, format);
2799     sys_format(&PyId_stderr, stderr, format, va);
2800     va_end(va);
2801 }
2802