diff options
| -rw-r--r-- | src/ChangeLog | 5 | ||||
| -rw-r--r-- | src/w32.c | 66 |
2 files changed, 47 insertions, 24 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 311e10765ec..0b3aa8e22ec 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,8 @@ | |||
| 1 | 2014-09-10 Eli Zaretskii <eliz@gnu.org> | ||
| 2 | |||
| 3 | * w32.c (sys_write): Use SAFE_NALLOCA for the NL -> CRLF | ||
| 4 | translation buffer. | ||
| 5 | |||
| 1 | 2014-09-10 Paul Eggert <eggert@cs.ucla.edu> | 6 | 2014-09-10 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 7 | ||
| 3 | * xterm.c (handle_one_xevent): Add braces to pacify gcc -Wall. | 8 | * xterm.c (handle_one_xevent): Add braces to pacify gcc -Wall. |
| @@ -8241,6 +8241,7 @@ int | |||
| 8241 | sys_write (int fd, const void * buffer, unsigned int count) | 8241 | sys_write (int fd, const void * buffer, unsigned int count) |
| 8242 | { | 8242 | { |
| 8243 | int nchars; | 8243 | int nchars; |
| 8244 | USE_SAFE_ALLOCA; | ||
| 8244 | 8245 | ||
| 8245 | if (fd < 0) | 8246 | if (fd < 0) |
| 8246 | { | 8247 | { |
| @@ -8259,30 +8260,33 @@ sys_write (int fd, const void * buffer, unsigned int count) | |||
| 8259 | /* Perform text mode translation if required. */ | 8260 | /* Perform text mode translation if required. */ |
| 8260 | if ((fd_info[fd].flags & FILE_BINARY) == 0) | 8261 | if ((fd_info[fd].flags & FILE_BINARY) == 0) |
| 8261 | { | 8262 | { |
| 8262 | char * tmpbuf = alloca (count * 2); | 8263 | char * tmpbuf; |
| 8263 | unsigned char * src = (void *)buffer; | 8264 | const unsigned char * src = buffer; |
| 8264 | unsigned char * dst = tmpbuf; | 8265 | unsigned char * dst; |
| 8265 | int nbytes = count; | 8266 | int nbytes = count; |
| 8266 | 8267 | ||
| 8268 | SAFE_NALLOCA (tmpbuf, 2, count); | ||
| 8269 | dst = tmpbuf; | ||
| 8270 | |||
| 8267 | while (1) | 8271 | while (1) |
| 8268 | { | 8272 | { |
| 8269 | unsigned char *next; | 8273 | unsigned char *next; |
| 8270 | /* copy next line or remaining bytes */ | 8274 | /* Copy next line or remaining bytes. */ |
| 8271 | next = _memccpy (dst, src, '\n', nbytes); | 8275 | next = _memccpy (dst, src, '\n', nbytes); |
| 8272 | if (next) | 8276 | if (next) |
| 8273 | { | 8277 | { |
| 8274 | /* copied one line ending with '\n' */ | 8278 | /* Copied one line ending with '\n'. */ |
| 8275 | int copied = next - dst; | 8279 | int copied = next - dst; |
| 8276 | nbytes -= copied; | 8280 | nbytes -= copied; |
| 8277 | src += copied; | 8281 | src += copied; |
| 8278 | /* insert '\r' before '\n' */ | 8282 | /* Insert '\r' before '\n'. */ |
| 8279 | next[-1] = '\r'; | 8283 | next[-1] = '\r'; |
| 8280 | next[0] = '\n'; | 8284 | next[0] = '\n'; |
| 8281 | dst = next + 1; | 8285 | dst = next + 1; |
| 8282 | count++; | 8286 | count++; |
| 8283 | } | 8287 | } |
| 8284 | else | 8288 | else |
| 8285 | /* copied remaining partial line -> now finished */ | 8289 | /* Copied remaining partial line -> now finished. */ |
| 8286 | break; | 8290 | break; |
| 8287 | } | 8291 | } |
| 8288 | buffer = tmpbuf; | 8292 | buffer = tmpbuf; |
| @@ -8296,31 +8300,44 @@ sys_write (int fd, const void * buffer, unsigned int count) | |||
| 8296 | HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent }; | 8300 | HANDLE wait_hnd[2] = { interrupt_handle, ovl->hEvent }; |
| 8297 | DWORD active = 0; | 8301 | DWORD active = 0; |
| 8298 | 8302 | ||
| 8303 | /* This is async (a.k.a. "overlapped") I/O, so the return value | ||
| 8304 | of FALSE from WriteFile means either an error or the output | ||
| 8305 | will be completed asynchronously (ERROR_IO_PENDING). */ | ||
| 8299 | if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl)) | 8306 | if (!WriteFile (hnd, buffer, count, (DWORD*) &nchars, ovl)) |
| 8300 | { | 8307 | { |
| 8301 | if (GetLastError () != ERROR_IO_PENDING) | 8308 | if (GetLastError () != ERROR_IO_PENDING) |
| 8302 | { | 8309 | { |
| 8303 | errno = EIO; | 8310 | errno = EIO; |
| 8304 | return -1; | 8311 | nchars = -1; |
| 8305 | } | 8312 | } |
| 8306 | if (detect_input_pending ()) | ||
| 8307 | active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE, | ||
| 8308 | QS_ALLINPUT); | ||
| 8309 | else | 8313 | else |
| 8310 | active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE); | ||
| 8311 | if (active == WAIT_OBJECT_0) | ||
| 8312 | { /* User pressed C-g, cancel write, then leave. Don't bother | ||
| 8313 | cleaning up as we may only get stuck in buggy drivers. */ | ||
| 8314 | PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR); | ||
| 8315 | CancelIo (hnd); | ||
| 8316 | errno = EIO; | ||
| 8317 | return -1; | ||
| 8318 | } | ||
| 8319 | if (active == WAIT_OBJECT_0 + 1 | ||
| 8320 | && !GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE)) | ||
| 8321 | { | 8314 | { |
| 8322 | errno = EIO; | 8315 | /* Wait for the write to complete, and watch C-g while |
| 8323 | return -1; | 8316 | at that. */ |
| 8317 | if (detect_input_pending ()) | ||
| 8318 | active = MsgWaitForMultipleObjects (2, wait_hnd, FALSE, | ||
| 8319 | INFINITE, QS_ALLINPUT); | ||
| 8320 | else | ||
| 8321 | active = WaitForMultipleObjects (2, wait_hnd, FALSE, INFINITE); | ||
| 8322 | switch (active) | ||
| 8323 | { | ||
| 8324 | case WAIT_OBJECT_0: | ||
| 8325 | /* User pressed C-g, cancel write, then leave. | ||
| 8326 | Don't bother cleaning up as we may only get stuck | ||
| 8327 | in buggy drivers. */ | ||
| 8328 | PurgeComm (hnd, PURGE_TXABORT | PURGE_TXCLEAR); | ||
| 8329 | CancelIo (hnd); | ||
| 8330 | errno = EIO; /* Why not EINTR? */ | ||
| 8331 | nchars = -1; | ||
| 8332 | break; | ||
| 8333 | case WAIT_OBJECT_0 + 1: | ||
| 8334 | if (!GetOverlappedResult (hnd, ovl, (DWORD*) &nchars, TRUE)) | ||
| 8335 | { | ||
| 8336 | errno = EIO; | ||
| 8337 | nchars = -1; | ||
| 8338 | } | ||
| 8339 | break; | ||
| 8340 | } | ||
| 8324 | } | 8341 | } |
| 8325 | } | 8342 | } |
| 8326 | } | 8343 | } |
| @@ -8381,6 +8398,7 @@ sys_write (int fd, const void * buffer, unsigned int count) | |||
| 8381 | } | 8398 | } |
| 8382 | } | 8399 | } |
| 8383 | 8400 | ||
| 8401 | SAFE_FREE (); | ||
| 8384 | return nchars; | 8402 | return nchars; |
| 8385 | } | 8403 | } |
| 8386 | 8404 | ||