diff --git a/Include/pythonrun.h b/Include/pythonrun.h index 98965b52a66..7bc011b1d23 100644 --- a/Include/pythonrun.h +++ b/Include/pythonrun.h @@ -113,9 +113,9 @@ PyAPI_FUNC(void) PyFloat_Fini(void); PyAPI_FUNC(void) PyOS_FiniInterrupts(void); /* Stuff with no proper home (yet) */ -PyAPI_FUNC(char *) PyOS_Readline(char *); +PyAPI_FUNC(char *) PyOS_Readline(FILE *, FILE *, char *); PyAPI_DATA(int) (*PyOS_InputHook)(void); -PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(char *); +PyAPI_DATA(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *); /* Stack size, in "pointers" (so we get extra safety margins on 64-bit platforms). On a 32-bit platform, this translates diff --git a/Modules/readline.c b/Modules/readline.c index 59ae8eb37d9..462d52f9b88 100644 --- a/Modules/readline.c +++ b/Modules/readline.c @@ -32,7 +32,7 @@ /* Pointers needed from outside (but not declared in a header file). */ extern DL_IMPORT(int) (*PyOS_InputHook)(void); -extern DL_IMPORT(char) *(*PyOS_ReadlineFunctionPointer)(char *); +extern DL_IMPORT(char) *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *,char *); /* Exported function to send one line to readline's init file parser */ @@ -606,12 +606,12 @@ onintr(int sig) /* Wrapper around GNU readline that handles signals differently. */ static char * -call_readline(char *prompt) +call_readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) { size_t n; char *p, *q; PyOS_sighandler_t old_inthandler; - + old_inthandler = PyOS_setsig(SIGINT, onintr); if (setjmp(jbuf)) { #ifdef HAVE_SIGRELSE @@ -622,6 +622,13 @@ call_readline(char *prompt) return NULL; } rl_event_hook = PyOS_InputHook; + + if (sys_stdin != rl_instream || sys_stdout != rl_outstream) { + rl_instream = sys_stdin; + rl_outstream = sys_stdout; + rl_prep_terminal (1); + } + p = readline(prompt); PyOS_setsig(SIGINT, old_inthandler); @@ -676,8 +683,7 @@ initreadline(void) m = Py_InitModule4("readline", readline_methods, doc_module, (PyObject *)NULL, PYTHON_API_VERSION); - if (isatty(fileno(stdin))) { - PyOS_ReadlineFunctionPointer = call_readline; - setup_readline(); - } + + PyOS_ReadlineFunctionPointer = call_readline; + setup_readline(); } diff --git a/Parser/myreadline.c b/Parser/myreadline.c index 8fe25ecb8fe..7b7ef7e2042 100644 --- a/Parser/myreadline.c +++ b/Parser/myreadline.c @@ -87,14 +87,14 @@ my_fgets(char *buf, int len, FILE *fp) /* Readline implementation using fgets() */ char * -PyOS_StdioReadline(char *prompt) +PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) { size_t n; char *p; n = 100; if ((p = PyMem_MALLOC(n)) == NULL) return NULL; - fflush(stdout); + fflush(sys_stdout); #ifndef RISCOS if (prompt) fprintf(stderr, "%s", prompt); @@ -107,7 +107,7 @@ PyOS_StdioReadline(char *prompt) } #endif fflush(stderr); - switch (my_fgets(p, (int)n, stdin)) { + switch (my_fgets(p, (int)n, sys_stdin)) { case 0: /* Normal case */ break; case 1: /* Interrupt */ @@ -135,7 +135,7 @@ PyOS_StdioReadline(char *prompt) if (incr > INT_MAX) { PyErr_SetString(PyExc_OverflowError, "input line too long"); } - if (my_fgets(p+n, (int)incr, stdin) != 0) + if (my_fgets(p+n, (int)incr, sys_stdin) != 0) break; n += strlen(p+n); } @@ -148,20 +148,32 @@ PyOS_StdioReadline(char *prompt) Note: Python expects in return a buffer allocated with PyMem_Malloc. */ -char *(*PyOS_ReadlineFunctionPointer)(char *); +char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *); /* Interface used by tokenizer.c and bltinmodule.c */ char * -PyOS_Readline(char *prompt) +PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt) { char *rv; + if (PyOS_ReadlineFunctionPointer == NULL) { - PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; + PyOS_ReadlineFunctionPointer = PyOS_StdioReadline; } + Py_BEGIN_ALLOW_THREADS - rv = (*PyOS_ReadlineFunctionPointer)(prompt); + + /* This is needed to handle the unlikely case that the + * interpreter is in interactive mode *and* stdin/out are not + * a tty. This can happen, for example if python is run like + * this: python -i < test1.py + */ + if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout))) + rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt); + else + rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout, + prompt); Py_END_ALLOW_THREADS return rv; } diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 749a59b68c2..8490ae9428d 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -18,7 +18,7 @@ #include "abstract.h" #endif /* PGEN */ -extern char *PyOS_Readline(char *); +extern char *PyOS_Readline(FILE *, FILE *, char *); /* Return malloc'ed string including trailing \n; empty malloc'ed string for EOF; NULL if interrupted */ @@ -671,7 +671,7 @@ tok_nextc(register struct tok_state *tok) return Py_CHARMASK(*tok->cur++); } if (tok->prompt != NULL) { - char *new = PyOS_Readline(tok->prompt); + char *new = PyOS_Readline(stdin, stdout, tok->prompt); if (tok->nextprompt != NULL) tok->prompt = tok->nextprompt; if (new == NULL) diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c index 2387deb667d..7e7ad2ef60c 100644 --- a/Python/bltinmodule.c +++ b/Python/bltinmodule.c @@ -1311,8 +1311,9 @@ builtin_raw_input(PyObject *self, PyObject *args) if (PyFile_WriteString(" ", fout) != 0) return NULL; } - if (PyFile_AsFile(fin) == stdin && PyFile_AsFile(fout) == stdout && - isatty(fileno(stdin)) && isatty(fileno(stdout))) { + if (PyFile_Check (fin) && PyFile_Check (fout) + && isatty(fileno(PyFile_AsFile(fin))) + && isatty(fileno(PyFile_AsFile(fout)))) { PyObject *po; char *prompt; char *s; @@ -1329,7 +1330,8 @@ builtin_raw_input(PyObject *self, PyObject *args) po = NULL; prompt = ""; } - s = PyOS_Readline(prompt); + s = PyOS_Readline(PyFile_AsFile (fin), PyFile_AsFile (fout), + prompt); Py_XDECREF(po); if (s == NULL) { PyErr_SetNone(PyExc_KeyboardInterrupt);