Line data Source code
1 :
2 : /* Readline interface for tokenizer.c and [raw_]input() in bltinmodule.c.
3 : By default, or when stdin is not a tty device, we have a super
4 : simple my_readline function using fgets.
5 : Optionally, we can use the GNU readline library.
6 : my_readline() has a different return value from GNU readline():
7 : - NULL if an interrupt occurred or if an error occurred
8 : - a malloc'ed empty string if EOF was read
9 : - a malloc'ed string ending in \n normally
10 : */
11 :
12 : #include "Python.h"
13 : #ifdef MS_WINDOWS
14 : #define WIN32_LEAN_AND_MEAN
15 : #include "windows.h"
16 : #endif /* MS_WINDOWS */
17 :
18 : #ifdef __VMS
19 : extern char* vms__StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt);
20 : #endif
21 :
22 :
23 : PyThreadState* _PyOS_ReadlineTState;
24 :
25 : #ifdef WITH_THREAD
26 : #include "pythread.h"
27 : static PyThread_type_lock _PyOS_ReadlineLock = NULL;
28 : #endif
29 :
30 : int (*PyOS_InputHook)(void) = NULL;
31 :
32 : /* This function restarts a fgets() after an EINTR error occurred
33 : except if PyOS_InterruptOccurred() returns true. */
34 :
35 : static int
36 0 : my_fgets(char *buf, int len, FILE *fp)
37 : {
38 : #ifdef MS_WINDOWS
39 : HANDLE hInterruptEvent;
40 : #endif
41 : char *p;
42 : int err;
43 : while (1) {
44 0 : if (PyOS_InputHook != NULL)
45 0 : (void)(PyOS_InputHook)();
46 0 : errno = 0;
47 0 : clearerr(fp);
48 : if (_PyVerify_fd(fileno(fp)))
49 0 : p = fgets(buf, len, fp);
50 : else
51 : p = NULL;
52 0 : if (p != NULL)
53 0 : return 0; /* No error */
54 0 : err = errno;
55 : #ifdef MS_WINDOWS
56 : /* Ctrl-C anywhere on the line or Ctrl-Z if the only character
57 : on a line will set ERROR_OPERATION_ABORTED. Under normal
58 : circumstances Ctrl-C will also have caused the SIGINT handler
59 : to fire which will have set the event object returned by
60 : _PyOS_SigintEvent. This signal fires in another thread and
61 : is not guaranteed to have occurred before this point in the
62 : code.
63 :
64 : Therefore: check whether the event is set with a small timeout.
65 : If it is, assume this is a Ctrl-C and reset the event. If it
66 : isn't set assume that this is a Ctrl-Z on its own and drop
67 : through to check for EOF.
68 : */
69 : if (GetLastError()==ERROR_OPERATION_ABORTED) {
70 : hInterruptEvent = _PyOS_SigintEvent();
71 : switch (WaitForSingleObject(hInterruptEvent, 10)) {
72 : case WAIT_OBJECT_0:
73 : ResetEvent(hInterruptEvent);
74 : return 1; /* Interrupt */
75 : case WAIT_FAILED:
76 : return -2; /* Error */
77 : }
78 : }
79 : #endif /* MS_WINDOWS */
80 0 : if (feof(fp)) {
81 0 : clearerr(fp);
82 0 : return -1; /* EOF */
83 : }
84 : #ifdef EINTR
85 0 : if (err == EINTR) {
86 : int s;
87 : #ifdef WITH_THREAD
88 0 : PyEval_RestoreThread(_PyOS_ReadlineTState);
89 : #endif
90 0 : s = PyErr_CheckSignals();
91 : #ifdef WITH_THREAD
92 0 : PyEval_SaveThread();
93 : #endif
94 0 : if (s < 0)
95 0 : return 1;
96 : /* try again */
97 0 : continue;
98 : }
99 : #endif
100 0 : if (PyOS_InterruptOccurred()) {
101 0 : return 1; /* Interrupt */
102 : }
103 0 : return -2; /* Error */
104 0 : }
105 : /* NOTREACHED */
106 : }
107 :
108 :
109 : /* Readline implementation using fgets() */
110 :
111 : char *
112 0 : PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
113 : {
114 : size_t n;
115 : char *p;
116 0 : n = 100;
117 0 : if ((p = (char *)PyMem_MALLOC(n)) == NULL)
118 0 : return NULL;
119 0 : fflush(sys_stdout);
120 0 : if (prompt)
121 0 : fprintf(stderr, "%s", prompt);
122 0 : fflush(stderr);
123 0 : switch (my_fgets(p, (int)n, sys_stdin)) {
124 : case 0: /* Normal case */
125 0 : break;
126 : case 1: /* Interrupt */
127 0 : PyMem_FREE(p);
128 0 : return NULL;
129 : case -1: /* EOF */
130 : case -2: /* Error */
131 : default: /* Shouldn't happen */
132 0 : *p = '\0';
133 0 : break;
134 : }
135 0 : n = strlen(p);
136 0 : while (n > 0 && p[n-1] != '\n') {
137 0 : size_t incr = n+2;
138 0 : p = (char *)PyMem_REALLOC(p, n + incr);
139 0 : if (p == NULL)
140 0 : return NULL;
141 0 : if (incr > INT_MAX) {
142 0 : PyErr_SetString(PyExc_OverflowError, "input line too long");
143 : }
144 0 : if (my_fgets(p+n, (int)incr, sys_stdin) != 0)
145 0 : break;
146 0 : n += strlen(p+n);
147 : }
148 0 : return (char *)PyMem_REALLOC(p, n+1);
149 : }
150 :
151 :
152 : /* By initializing this function pointer, systems embedding Python can
153 : override the readline function.
154 :
155 : Note: Python expects in return a buffer allocated with PyMem_Malloc. */
156 :
157 : char *(*PyOS_ReadlineFunctionPointer)(FILE *, FILE *, char *);
158 :
159 :
160 : /* Interface used by tokenizer.c and bltinmodule.c */
161 :
162 : char *
163 0 : PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, char *prompt)
164 : {
165 : char *rv;
166 :
167 0 : if (_PyOS_ReadlineTState == PyThreadState_GET()) {
168 0 : PyErr_SetString(PyExc_RuntimeError,
169 : "can't re-enter readline");
170 0 : return NULL;
171 : }
172 :
173 :
174 0 : if (PyOS_ReadlineFunctionPointer == NULL) {
175 : #ifdef __VMS
176 : PyOS_ReadlineFunctionPointer = vms__StdioReadline;
177 : #else
178 0 : PyOS_ReadlineFunctionPointer = PyOS_StdioReadline;
179 : #endif
180 : }
181 :
182 : #ifdef WITH_THREAD
183 0 : if (_PyOS_ReadlineLock == NULL) {
184 0 : _PyOS_ReadlineLock = PyThread_allocate_lock();
185 : }
186 : #endif
187 :
188 0 : _PyOS_ReadlineTState = PyThreadState_GET();
189 0 : Py_BEGIN_ALLOW_THREADS
190 : #ifdef WITH_THREAD
191 0 : PyThread_acquire_lock(_PyOS_ReadlineLock, 1);
192 : #endif
193 :
194 : /* This is needed to handle the unlikely case that the
195 : * interpreter is in interactive mode *and* stdin/out are not
196 : * a tty. This can happen, for example if python is run like
197 : * this: python -i < test1.py
198 : */
199 0 : if (!isatty (fileno (sys_stdin)) || !isatty (fileno (sys_stdout)))
200 0 : rv = PyOS_StdioReadline (sys_stdin, sys_stdout, prompt);
201 : else
202 0 : rv = (*PyOS_ReadlineFunctionPointer)(sys_stdin, sys_stdout,
203 : prompt);
204 0 : Py_END_ALLOW_THREADS
205 :
206 : #ifdef WITH_THREAD
207 0 : PyThread_release_lock(_PyOS_ReadlineLock);
208 : #endif
209 :
210 0 : _PyOS_ReadlineTState = NULL;
211 :
212 0 : return rv;
213 : }
|