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