• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Python interpreter main program */
2 
3 #include "Python.h"
4 #include "osdefs.h"
5 #include "code.h" /* For CO_FUTURE_DIVISION */
6 #include "import.h"
7 
8 #ifdef __VMS
9 #include <unixlib.h>
10 #endif
11 
12 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
13 #ifdef HAVE_FCNTL_H
14 #include <fcntl.h>
15 #endif
16 #endif
17 
18 #if (defined(PYOS_OS2) && !defined(PYCC_GCC)) || defined(MS_WINDOWS)
19 #define PYTHONHOMEHELP "<prefix>\\lib"
20 #else
21 #if defined(PYOS_OS2) && defined(PYCC_GCC)
22 #define PYTHONHOMEHELP "<prefix>/Lib"
23 #else
24 #define PYTHONHOMEHELP "<prefix>/pythonX.X"
25 #endif
26 #endif
27 
28 #include "pygetopt.h"
29 
30 #define COPYRIGHT \
31     "Type \"help\", \"copyright\", \"credits\" or \"license\" " \
32     "for more information."
33 
34 #ifdef __cplusplus
35 extern "C" {
36 #endif
37 
38 /* For Py_GetArgcArgv(); set by main() */
39 static char **orig_argv;
40 static int  orig_argc;
41 
42 /* command line options */
43 #define BASE_OPTS "3bBc:dEhiJm:OQ:RsStuUvVW:xX?"
44 
45 #ifndef RISCOS
46 #define PROGRAM_OPTS BASE_OPTS
47 #else /*RISCOS*/
48 /* extra option saying that we are running under a special task window
49    frontend; especially my_readline will behave different */
50 #define PROGRAM_OPTS BASE_OPTS "w"
51 /* corresponding flag */
52 extern int Py_RISCOSWimpFlag;
53 #endif /*RISCOS*/
54 
55 /* Short usage message (with %s for argv0) */
56 static char *usage_line =
57 "usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...\n";
58 
59 /* Long usage message, split into parts < 512 bytes */
60 static char *usage_1 = "\
61 Options and arguments (and corresponding environment variables):\n\
62 -B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x\n\
63 -c cmd : program passed in as string (terminates option list)\n\
64 -d     : debug output from parser; also PYTHONDEBUG=x\n\
65 -E     : ignore PYTHON* environment variables (such as PYTHONPATH)\n\
66 -h     : print this help message and exit (also --help)\n\
67 -i     : inspect interactively after running script; forces a prompt even\n\
68 ";
69 static char *usage_2 = "\
70          if stdin does not appear to be a terminal; also PYTHONINSPECT=x\n\
71 -m mod : run library module as a script (terminates option list)\n\
72 -O     : optimize generated bytecode slightly; also PYTHONOPTIMIZE=x\n\
73 -OO    : remove doc-strings in addition to the -O optimizations\n\
74 -R     : use a pseudo-random salt to make hash() values of various types be\n\
75          unpredictable between separate invocations of the interpreter, as\n\
76          a defense against denial-of-service attacks\n\
77 -Q arg : division options: -Qold (default), -Qwarn, -Qwarnall, -Qnew\n\
78 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE\n\
79 -S     : don't imply 'import site' on initialization\n\
80 -t     : issue warnings about inconsistent tab usage (-tt: issue errors)\n\
81 ";
82 static char *usage_3 = "\
83 -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x\n\
84          see man page for details on internal buffering relating to '-u'\n\
85 -v     : verbose (trace import statements); also PYTHONVERBOSE=x\n\
86          can be supplied multiple times to increase verbosity\n\
87 -V     : print the Python version number and exit (also --version)\n\
88 -W arg : warning control; arg is action:message:category:module:lineno\n\
89          also PYTHONWARNINGS=arg\n\
90 -x     : skip first line of source, allowing use of non-Unix forms of #!cmd\n\
91 ";
92 static char *usage_4 = "\
93 -3     : warn about Python 3.x incompatibilities that 2to3 cannot trivially fix\n\
94 file   : program read from script file\n\
95 -      : program read from stdin (default; interactive mode if a tty)\n\
96 arg ...: arguments passed to program in sys.argv[1:]\n\n\
97 Other environment variables:\n\
98 PYTHONSTARTUP: file executed on interactive startup (no default)\n\
99 PYTHONPATH   : '%c'-separated list of directories prefixed to the\n\
100                default module search path.  The result is sys.path.\n\
101 ";
102 static char *usage_5 = "\
103 PYTHONHOME   : alternate <prefix> directory (or <prefix>%c<exec_prefix>).\n\
104                The default module search path uses %s.\n\
105 PYTHONCASEOK : ignore case in 'import' statements (Windows).\n\
106 PYTHONIOENCODING: Encoding[:errors] used for stdin/stdout/stderr.\n\
107 ";
108 static char *usage_6 = "\
109 PYTHONHASHSEED: if this variable is set to 'random', the effect is the same\n\
110    as specifying the -R option: a random value is used to seed the hashes of\n\
111    str, bytes and datetime objects.  It can also be set to an integer\n\
112    in the range [0,4294967295] to get hash values with a predictable seed.\n\
113 ";
114 
115 
116 static int
usage(int exitcode,char * program)117 usage(int exitcode, char* program)
118 {
119     FILE *f = exitcode ? stderr : stdout;
120 
121     fprintf(f, usage_line, program);
122     if (exitcode)
123         fprintf(f, "Try `python -h' for more information.\n");
124     else {
125         fputs(usage_1, f);
126         fputs(usage_2, f);
127         fputs(usage_3, f);
128         fprintf(f, usage_4, DELIM);
129         fprintf(f, usage_5, DELIM, PYTHONHOMEHELP);
130         fputs(usage_6, f);
131     }
132 #if defined(__VMS)
133     if (exitcode == 0) {
134         /* suppress 'error' message */
135         return 1;
136     }
137     else {
138         /* STS$M_INHIB_MSG + SS$_ABORT */
139         return 0x1000002c;
140     }
141 #else
142     return exitcode;
143 #endif
144     /*NOTREACHED*/
145 }
146 
RunStartupFile(PyCompilerFlags * cf)147 static void RunStartupFile(PyCompilerFlags *cf)
148 {
149     char *startup = Py_GETENV("PYTHONSTARTUP");
150     if (startup != NULL && startup[0] != '\0') {
151         FILE *fp = fopen(startup, "r");
152         if (fp != NULL) {
153             (void) PyRun_SimpleFileExFlags(fp, startup, 0, cf);
154             PyErr_Clear();
155             fclose(fp);
156         } else {
157             int save_errno;
158             save_errno = errno;
159             PySys_WriteStderr("Could not open PYTHONSTARTUP\n");
160             errno = save_errno;
161             PyErr_SetFromErrnoWithFilename(PyExc_IOError,
162                                            startup);
163             PyErr_Print();
164             PyErr_Clear();
165         }
166     }
167 }
168 
169 
RunModule(char * module,int set_argv0)170 static int RunModule(char *module, int set_argv0)
171 {
172     PyObject *runpy, *runmodule, *runargs, *result;
173     runpy = PyImport_ImportModule("runpy");
174     if (runpy == NULL) {
175         fprintf(stderr, "Could not import runpy module\n");
176         return -1;
177     }
178     runmodule = PyObject_GetAttrString(runpy, "_run_module_as_main");
179     if (runmodule == NULL) {
180         fprintf(stderr, "Could not access runpy._run_module_as_main\n");
181         Py_DECREF(runpy);
182         return -1;
183     }
184     runargs = Py_BuildValue("(si)", module, set_argv0);
185     if (runargs == NULL) {
186         fprintf(stderr,
187             "Could not create arguments for runpy._run_module_as_main\n");
188         Py_DECREF(runpy);
189         Py_DECREF(runmodule);
190         return -1;
191     }
192     result = PyObject_Call(runmodule, runargs, NULL);
193     if (result == NULL) {
194         PyErr_Print();
195     }
196     Py_DECREF(runpy);
197     Py_DECREF(runmodule);
198     Py_DECREF(runargs);
199     if (result == NULL) {
200         return -1;
201     }
202     Py_DECREF(result);
203     return 0;
204 }
205 
RunMainFromImporter(char * filename)206 static int RunMainFromImporter(char *filename)
207 {
208     PyObject *argv0 = NULL, *importer = NULL;
209 
210     if ((argv0 = PyString_FromString(filename)) &&
211         (importer = PyImport_GetImporter(argv0)) &&
212         (importer->ob_type != &PyNullImporter_Type))
213     {
214              /* argv0 is usable as an import source, so
215                     put it in sys.path[0] and import __main__ */
216         PyObject *sys_path = NULL;
217         if ((sys_path = PySys_GetObject("path")) &&
218             !PyList_SetItem(sys_path, 0, argv0))
219         {
220             Py_INCREF(argv0);
221             Py_DECREF(importer);
222             sys_path = NULL;
223             return RunModule("__main__", 0) != 0;
224         }
225     }
226     Py_XDECREF(argv0);
227     Py_XDECREF(importer);
228     if (PyErr_Occurred()) {
229         PyErr_Print();
230         return 1;
231     }
232     return -1;
233 }
234 
235 
236 /* Main program */
237 
238 int
Py_Main(int argc,char ** argv)239 Py_Main(int argc, char **argv)
240 {
241     int c;
242     int sts;
243     char *command = NULL;
244     char *filename = NULL;
245     char *module = NULL;
246     FILE *fp = stdin;
247     char *p;
248     int unbuffered = 0;
249     int skipfirstline = 0;
250     int stdin_is_interactive = 0;
251     int help = 0;
252     int version = 0;
253     int saw_unbuffered_flag = 0;
254     PyCompilerFlags cf;
255 
256     cf.cf_flags = 0;
257 
258     orig_argc = argc;           /* For Py_GetArgcArgv() */
259     orig_argv = argv;
260 
261 #ifdef RISCOS
262     Py_RISCOSWimpFlag = 0;
263 #endif
264 
265     /* Hash randomization needed early for all string operations
266        (including -W and -X options). */
267     _PyOS_opterr = 0;  /* prevent printing the error in 1st pass */
268     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
269         if (c == 'm' || c == 'c') {
270             /* -c / -m is the last option: following arguments are
271                not interpreter options. */
272             break;
273         }
274         switch (c) {
275         case 'E':
276             Py_IgnoreEnvironmentFlag++;
277             break;
278         case 'R':
279             Py_HashRandomizationFlag++;
280             break;
281         }
282     }
283     /* The variable is only tested for existence here; _PyRandom_Init will
284        check its value further. */
285     if (!Py_HashRandomizationFlag &&
286         (p = Py_GETENV("PYTHONHASHSEED")) && *p != '\0')
287         Py_HashRandomizationFlag = 1;
288 
289     _PyRandom_Init();
290 
291     PySys_ResetWarnOptions();
292     _PyOS_ResetGetOpt();
293 
294     while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) {
295         if (c == 'c') {
296             /* -c is the last option; following arguments
297                that look like options are left for the
298                command to interpret. */
299             command = (char *)malloc(strlen(_PyOS_optarg) + 2);
300             if (command == NULL)
301                 Py_FatalError(
302                    "not enough memory to copy -c argument");
303             strcpy(command, _PyOS_optarg);
304             strcat(command, "\n");
305             break;
306         }
307 
308         if (c == 'm') {
309             /* -m is the last option; following arguments
310                that look like options are left for the
311                module to interpret. */
312             module = (char *)malloc(strlen(_PyOS_optarg) + 2);
313             if (module == NULL)
314                 Py_FatalError(
315                    "not enough memory to copy -m argument");
316             strcpy(module, _PyOS_optarg);
317             break;
318         }
319 
320         switch (c) {
321         case 'b':
322             Py_BytesWarningFlag++;
323             break;
324 
325         case 'd':
326             Py_DebugFlag++;
327             break;
328 
329         case '3':
330             Py_Py3kWarningFlag++;
331             if (!Py_DivisionWarningFlag)
332                 Py_DivisionWarningFlag = 1;
333             break;
334 
335         case 'Q':
336             if (strcmp(_PyOS_optarg, "old") == 0) {
337                 Py_DivisionWarningFlag = 0;
338                 break;
339             }
340             if (strcmp(_PyOS_optarg, "warn") == 0) {
341                 Py_DivisionWarningFlag = 1;
342                 break;
343             }
344             if (strcmp(_PyOS_optarg, "warnall") == 0) {
345                 Py_DivisionWarningFlag = 2;
346                 break;
347             }
348             if (strcmp(_PyOS_optarg, "new") == 0) {
349                 /* This only affects __main__ */
350                 cf.cf_flags |= CO_FUTURE_DIVISION;
351                 /* And this tells the eval loop to treat
352                    BINARY_DIVIDE as BINARY_TRUE_DIVIDE */
353                 _Py_QnewFlag = 1;
354                 break;
355             }
356             fprintf(stderr,
357                 "-Q option should be `-Qold', "
358                 "`-Qwarn', `-Qwarnall', or `-Qnew' only\n");
359             return usage(2, argv[0]);
360             /* NOTREACHED */
361 
362         case 'i':
363             Py_InspectFlag++;
364             Py_InteractiveFlag++;
365             break;
366 
367         /* case 'J': reserved for Jython */
368 
369         case 'O':
370             Py_OptimizeFlag++;
371             break;
372 
373         case 'B':
374             Py_DontWriteBytecodeFlag++;
375             break;
376 
377         case 's':
378             Py_NoUserSiteDirectory++;
379             break;
380 
381         case 'S':
382             Py_NoSiteFlag++;
383             break;
384 
385         case 'E':
386             /* Already handled above */
387             break;
388 
389         case 't':
390             Py_TabcheckFlag++;
391             break;
392 
393         case 'u':
394             unbuffered++;
395             saw_unbuffered_flag = 1;
396             break;
397 
398         case 'v':
399             Py_VerboseFlag++;
400             break;
401 
402 #ifdef RISCOS
403         case 'w':
404             Py_RISCOSWimpFlag = 1;
405             break;
406 #endif
407 
408         case 'x':
409             skipfirstline = 1;
410             break;
411 
412         /* case 'X': reserved for implementation-specific arguments */
413 
414         case 'U':
415             Py_UnicodeFlag++;
416             break;
417         case 'h':
418         case '?':
419             help++;
420             break;
421         case 'V':
422             version++;
423             break;
424 
425         case 'W':
426             PySys_AddWarnOption(_PyOS_optarg);
427             break;
428 
429         case 'R':
430             /* Already handled above */
431             break;
432 
433         /* This space reserved for other options */
434 
435         default:
436             return usage(2, argv[0]);
437             /*NOTREACHED*/
438 
439         }
440     }
441 
442     if (help)
443         return usage(0, argv[0]);
444 
445     if (version) {
446         fprintf(stderr, "Python %s\n", PY_VERSION);
447         return 0;
448     }
449 
450     if (Py_Py3kWarningFlag && !Py_TabcheckFlag)
451         /* -3 implies -t (but not -tt) */
452         Py_TabcheckFlag = 1;
453 
454     if (!Py_InspectFlag &&
455         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
456         Py_InspectFlag = 1;
457     if (!saw_unbuffered_flag &&
458         (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0')
459         unbuffered = 1;
460 
461     if (!Py_NoUserSiteDirectory &&
462         (p = Py_GETENV("PYTHONNOUSERSITE")) && *p != '\0')
463         Py_NoUserSiteDirectory = 1;
464 
465     if ((p = Py_GETENV("PYTHONWARNINGS")) && *p != '\0') {
466         char *buf, *warning;
467 
468         buf = (char *)malloc(strlen(p) + 1);
469         if (buf == NULL)
470             Py_FatalError(
471                "not enough memory to copy PYTHONWARNINGS");
472         strcpy(buf, p);
473         for (warning = strtok(buf, ",");
474              warning != NULL;
475              warning = strtok(NULL, ","))
476             PySys_AddWarnOption(warning);
477         free(buf);
478     }
479 
480     if (command == NULL && module == NULL && _PyOS_optind < argc &&
481         strcmp(argv[_PyOS_optind], "-") != 0)
482     {
483 #ifdef __VMS
484         filename = decc$translate_vms(argv[_PyOS_optind]);
485         if (filename == (char *)0 || filename == (char *)-1)
486             filename = argv[_PyOS_optind];
487 
488 #else
489         filename = argv[_PyOS_optind];
490 #endif
491     }
492 
493     stdin_is_interactive = Py_FdIsInteractive(stdin, (char *)0);
494 
495     if (unbuffered) {
496 #if defined(MS_WINDOWS) || defined(__CYGWIN__)
497         _setmode(fileno(stdin), O_BINARY);
498         _setmode(fileno(stdout), O_BINARY);
499 #endif
500 #ifdef HAVE_SETVBUF
501         setvbuf(stdin,  (char *)NULL, _IONBF, BUFSIZ);
502         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
503         setvbuf(stderr, (char *)NULL, _IONBF, BUFSIZ);
504 #else /* !HAVE_SETVBUF */
505         setbuf(stdin,  (char *)NULL);
506         setbuf(stdout, (char *)NULL);
507         setbuf(stderr, (char *)NULL);
508 #endif /* !HAVE_SETVBUF */
509     }
510     else if (Py_InteractiveFlag) {
511 #ifdef MS_WINDOWS
512         /* Doesn't have to have line-buffered -- use unbuffered */
513         /* Any set[v]buf(stdin, ...) screws up Tkinter :-( */
514         setvbuf(stdout, (char *)NULL, _IONBF, BUFSIZ);
515 #else /* !MS_WINDOWS */
516 #ifdef HAVE_SETVBUF
517         setvbuf(stdin,  (char *)NULL, _IOLBF, BUFSIZ);
518         setvbuf(stdout, (char *)NULL, _IOLBF, BUFSIZ);
519 #endif /* HAVE_SETVBUF */
520 #endif /* !MS_WINDOWS */
521         /* Leave stderr alone - it should be unbuffered anyway. */
522     }
523 #ifdef __VMS
524     else {
525         setvbuf (stdout, (char *)NULL, _IOLBF, BUFSIZ);
526     }
527 #endif /* __VMS */
528 
529 #ifdef __APPLE__
530     /* On MacOS X, when the Python interpreter is embedded in an
531        application bundle, it gets executed by a bootstrapping script
532        that does os.execve() with an argv[0] that's different from the
533        actual Python executable. This is needed to keep the Finder happy,
534        or rather, to work around Apple's overly strict requirements of
535        the process name. However, we still need a usable sys.executable,
536        so the actual executable path is passed in an environment variable.
537        See Lib/plat-mac/bundlebuiler.py for details about the bootstrap
538        script. */
539     if ((p = Py_GETENV("PYTHONEXECUTABLE")) && *p != '\0')
540         Py_SetProgramName(p);
541     else
542         Py_SetProgramName(argv[0]);
543 #else
544     Py_SetProgramName(argv[0]);
545 #endif
546     Py_Initialize();
547 
548     if (Py_VerboseFlag ||
549         (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) {
550         fprintf(stderr, "Python %s on %s\n",
551             Py_GetVersion(), Py_GetPlatform());
552         if (!Py_NoSiteFlag)
553             fprintf(stderr, "%s\n", COPYRIGHT);
554     }
555 
556     if (command != NULL) {
557         /* Backup _PyOS_optind and force sys.argv[0] = '-c' */
558         _PyOS_optind--;
559         argv[_PyOS_optind] = "-c";
560     }
561 
562     if (module != NULL) {
563         /* Backup _PyOS_optind and force sys.argv[0] = '-c'
564            so that PySys_SetArgv correctly sets sys.path[0] to ''
565            rather than looking for a file called "-m". See
566            tracker issue #8202 for details. */
567         _PyOS_optind--;
568         argv[_PyOS_optind] = "-c";
569     }
570 
571     PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);
572 
573     if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) &&
574         isatty(fileno(stdin))) {
575         PyObject *v;
576         v = PyImport_ImportModule("readline");
577         if (v == NULL)
578             PyErr_Clear();
579         else
580             Py_DECREF(v);
581     }
582 
583     if (command) {
584         sts = PyRun_SimpleStringFlags(command, &cf) != 0;
585         free(command);
586     } else if (module) {
587         sts = (RunModule(module, 1) != 0);
588         free(module);
589     }
590     else {
591 
592         if (filename == NULL && stdin_is_interactive) {
593             Py_InspectFlag = 0; /* do exit on SystemExit */
594             RunStartupFile(&cf);
595         }
596         /* XXX */
597 
598         sts = -1;               /* keep track of whether we've already run __main__ */
599 
600         if (filename != NULL) {
601             sts = RunMainFromImporter(filename);
602         }
603 
604         if (sts==-1 && filename!=NULL) {
605             if ((fp = fopen(filename, "r")) == NULL) {
606                 fprintf(stderr, "%s: can't open file '%s': [Errno %d] %s\n",
607                     argv[0], filename, errno, strerror(errno));
608 
609                 return 2;
610             }
611             else if (skipfirstline) {
612                 int ch;
613                 /* Push back first newline so line numbers
614                    remain the same */
615                 while ((ch = getc(fp)) != EOF) {
616                     if (ch == '\n') {
617                         (void)ungetc(ch, fp);
618                         break;
619                     }
620                 }
621             }
622             {
623                 /* XXX: does this work on Win/Win64? (see posix_fstat) */
624                 struct stat sb;
625                 if (fstat(fileno(fp), &sb) == 0 &&
626                     S_ISDIR(sb.st_mode)) {
627                     fprintf(stderr, "%s: '%s' is a directory, cannot continue\n", argv[0], filename);
628                     fclose(fp);
629                     return 1;
630                 }
631             }
632         }
633 
634         if (sts==-1) {
635             /* call pending calls like signal handlers (SIGINT) */
636             if (Py_MakePendingCalls() == -1) {
637                 PyErr_Print();
638                 sts = 1;
639             } else {
640                 sts = PyRun_AnyFileExFlags(
641                     fp,
642                     filename == NULL ? "<stdin>" : filename,
643                     filename != NULL, &cf) != 0;
644             }
645         }
646 
647     }
648 
649     /* Check this environment variable at the end, to give programs the
650      * opportunity to set it from Python.
651      */
652     if (!Py_InspectFlag &&
653         (p = Py_GETENV("PYTHONINSPECT")) && *p != '\0')
654     {
655         Py_InspectFlag = 1;
656     }
657 
658     if (Py_InspectFlag && stdin_is_interactive &&
659         (filename != NULL || command != NULL || module != NULL)) {
660         Py_InspectFlag = 0;
661         /* XXX */
662         sts = PyRun_AnyFileFlags(stdin, "<stdin>", &cf) != 0;
663     }
664 
665     Py_Finalize();
666 #ifdef RISCOS
667     if (Py_RISCOSWimpFlag)
668         fprintf(stderr, "\x0cq\x0c"); /* make frontend quit */
669 #endif
670 
671 #ifdef __INSURE__
672     /* Insure++ is a memory analysis tool that aids in discovering
673      * memory leaks and other memory problems.  On Python exit, the
674      * interned string dictionary is flagged as being in use at exit
675      * (which it is).  Under normal circumstances, this is fine because
676      * the memory will be automatically reclaimed by the system.  Under
677      * memory debugging, it's a huge source of useless noise, so we
678      * trade off slower shutdown for less distraction in the memory
679      * reports.  -baw
680      */
681     _Py_ReleaseInternedStrings();
682 #endif /* __INSURE__ */
683 
684     return sts;
685 }
686 
687 /* this is gonna seem *real weird*, but if you put some other code between
688    Py_Main() and Py_GetArgcArgv() you will need to adjust the test in the
689    while statement in Misc/gdbinit:ppystack */
690 
691 /* Make the *original* argc/argv available to other modules.
692    This is rare, but it is needed by the secureware extension. */
693 
694 void
Py_GetArgcArgv(int * argc,char *** argv)695 Py_GetArgcArgv(int *argc, char ***argv)
696 {
697     *argc = orig_argc;
698     *argv = orig_argv;
699 }
700 
701 #ifdef __cplusplus
702 }
703 #endif
704 
705