]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/dtable.cc
Cygwin: add release message for latest pipe changes
[newlib-cygwin.git] / winsup / cygwin / dtable.cc
CommitLineData
9015e0fb 1/* dtable.cc: file descriptor support.
1fd5e000 2
1fd5e000
CF
3This file is part of Cygwin.
4
5This software is a copyrighted work licensed under the terms of the
6Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7details. */
8
9#define __INSIDE_CYGWIN_NET__
10
4c8d72de 11#include "winsup.h"
1fd5e000
CF
12#include <stdlib.h>
13#include <stdio.h>
1fd5e000 14#include <unistd.h>
1ffe3e67 15#include <wchar.h>
1fd5e000 16
a1299ba5 17#define USE_SYS_TYPES_FD_SET
d0b178fe 18#include <winsock.h>
e2ebe117 19#include "pinfo.h"
9e2baf8d 20#include "cygerrno.h"
95a8465b 21#include "perprocess.h"
bccd5e0d 22#include "path.h"
7ac61736 23#include "fhandler.h"
b4fa8164 24#include "select.h"
bccd5e0d 25#include "dtable.h"
0381fec6 26#include "cygheap.h"
ab5d348d 27#include "tls_pbuf.h"
2402700d 28#include "ntdll.h"
f09acf77 29#include "shared_info.h"
1fd5e000 30
61522196
CV
31static const DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
32 STD_ERROR_HANDLE};
164a681c 33
88f0dc31 34static bool handle_to_fn (HANDLE, char *);
1ffe3e67
CF
35
36#define WCLEN(x) ((sizeof (x) / sizeof (WCHAR)) - 1)
c8a66289
CF
37static const char unknown_file[] = "some disk file";
38static const WCHAR DEV_NULL[] = L"\\Device\\Null";
019fc8d8 39static const WCHAR DEV_SOCKET[] = L"\\Device\\Afd";
1ffe3e67 40
c8a66289
CF
41static const WCHAR DEVICE_PREFIX[] = L"\\device\\";
42static const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX);
1ffe3e67
CF
43
44static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\";
45static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE);
dd76747b 46
1ffe3e67
CF
47static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\";
48static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE);
49
50static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\";
51static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1);
634a4140 52
1fd5e000
CF
53/* Set aside space for the table of fds */
54void
2d1d1eb1 55dtable_init ()
1fd5e000 56{
0381fec6 57 if (!cygheap->fdtab.size)
09244c00 58 cygheap->fdtab.extend (NOFILE_INCR, 0);
1fd5e000
CF
59}
60
30c5411d 61void
1fd5e000
CF
62set_std_handle (int fd)
63{
30fa1549 64 fhandler_base *fh = cygheap->fdtab[fd];
1fd5e000 65 if (fd == 0)
30fa1549 66 SetStdHandle (std_consts[fd], fh ? fh->get_handle () : NULL);
164a681c 67 else if (fd <= 2)
30fa1549 68 SetStdHandle (std_consts[fd], fh ? fh->get_output_handle () : NULL);
1fd5e000
CF
69}
70
71int
09244c00 72dtable::extend (size_t howmuch, size_t min)
1fd5e000 73{
eeaa47ef 74 size_t new_size = size + howmuch;
1fd5e000
CF
75 fhandler_base **newfds;
76
5b8358e6 77 if (new_size <= OPEN_MAX)
09244c00 78 /* ok */;
5b8358e6
KB
79 else if (size < OPEN_MAX && min < OPEN_MAX)
80 new_size = OPEN_MAX;
09244c00 81 else
4d782b42
CF
82 {
83 set_errno (EMFILE);
84 return 0;
85 }
86
c729f227 87 /* Try to allocate more space for fd table. We can't call realloc ()
1fd5e000
CF
88 here to preserve old table if memory allocation fails */
89
b0e82b74 90 if (!(newfds = (fhandler_base **) ccalloc (HEAP_ARGV, new_size, sizeof newfds[0])))
1fd5e000
CF
91 {
92 debug_printf ("calloc failed");
4d782b42 93 set_errno (ENOMEM);
1fd5e000
CF
94 return 0;
95 }
96 if (fds)
97 {
4d782b42 98 memcpy (newfds, fds, size * sizeof (fds[0]));
3301015b 99 cfree (fds);
1fd5e000
CF
100 }
101
102 size = new_size;
103 fds = newfds;
61522196 104 debug_printf ("size %ld, fds %p", size, fds);
1fd5e000
CF
105 return 1;
106}
107
083abe54
CF
108void
109dtable::get_debugger_info ()
110{
3c4f2024
CF
111 extern bool jit_debug;
112 if (!jit_debug && being_debugged ())
083abe54 113 {
23771fa1 114 char std[3][sizeof ("/dev/ptyNNNN")];
083abe54 115 std[0][0] = std[1][0] = std [2][0] = '\0';
61522196
CV
116 char buf[sizeof ("cYgstd %x") + 64];
117 sprintf (buf, "cYgstd %p %zx %x", &std, sizeof (std[0]), 3);
083abe54
CF
118 OutputDebugString (buf);
119 for (int i = 0; i < 3; i++)
120 if (std[i][0])
121 {
083abe54 122 HANDLE h = GetStdHandle (std_consts[i]);
7ac61736 123 fhandler_base *fh = build_fh_name (std[i]);
083abe54
CF
124 if (!fh)
125 continue;
7ac61736 126 fds[i] = fh;
061095b5
CV
127 if (!fh->open ((i ? (i == 2 ? O_RDWR : O_WRONLY) : O_RDONLY)
128 | O_BINARY, 0777))
083abe54
CF
129 release (i);
130 else
8f19b4b6
CV
131 {
132 CloseHandle (h);
133 /* Copy to Windows' idea of a standard handle, otherwise
134 we have invalid standard handles when calling Windows
135 functions (small_printf and strace might suffer, too). */
136 SetStdHandle (std_consts[i], i ? fh->get_output_handle ()
137 : fh->get_handle ());
138 }
083abe54
CF
139 }
140 }
141}
142
1fd5e000 143/* Initialize the file descriptor/handle mapping table.
10dedaaa
CF
144 This function should only be called when a cygwin function is invoked
145 by a non-cygwin function, i.e., it should only happen very rarely. */
1fd5e000
CF
146
147void
083abe54 148dtable::stdio_init ()
1fd5e000 149{
8cb359d9 150 if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
3eb92a58 151 {
44d2fc0a 152 tty_min *t = cygwin_shared->tty.get_cttyp ();
a345dc55 153 if (t && t->is_console)
f09acf77 154 init_console_handler (true);
3eb92a58
CF
155 return;
156 }
1fd5e000 157
083abe54
CF
158 HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
159 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
160 HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
1fd5e000 161
54030e21 162 init_std_file_from_handle (0, in);
083abe54
CF
163
164 /* STD_ERROR_HANDLE has been observed to be the same as
165 STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes
166 to pass data from child to parent). */
edf5a5bd
CV
167 /* CV 2008-10-17: Under debugger control, std fd's have been potentially
168 initialized in dtable::get_debugger_info (). In this case
169 init_std_file_from_handle is a no-op, so, even if out == err we don't
170 want to duplicate the handle since it will be unused. */
8f19b4b6 171 if (out == err && (!being_debugged () || not_open (2)))
083abe54
CF
172 {
173 /* Since this code is not invoked for forked tasks, we don't have
174 to worry about the close-on-exec flag here. */
7bdbf062
CV
175 if (!DuplicateHandle (GetCurrentProcess (), out,
176 GetCurrentProcess (), &err,
177 0, TRUE, DUPLICATE_SAME_ACCESS))
1fd5e000 178 {
083abe54
CF
179 /* If that fails, do this as a fall back. */
180 err = out;
7bdbf062 181 system_printf ("couldn't make stderr distinct from stdout, %E");
1fd5e000 182 }
1fd5e000 183 }
083abe54 184
54030e21
CF
185 init_std_file_from_handle (1, out);
186 init_std_file_from_handle (2, err);
1fd5e000
CF
187}
188
8e10c431
CF
189const int dtable::initial_archetype_size;
190
191fhandler_base *
192dtable::find_archetype (device& dev)
193{
194 for (unsigned i = 0; i < farchetype; i++)
61522196 195 if (archetypes[i]->get_device () == (dev_t) dev)
8e10c431
CF
196 return archetypes[i];
197 return NULL;
198}
199
200fhandler_base **
201dtable::add_archetype ()
202{
203 if (farchetype++ >= narchetypes)
634a4140 204 archetypes = (fhandler_base **) crealloc_abort (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
8e10c431
CF
205 return archetypes + farchetype - 1;
206}
207
208void
209dtable::delete_archetype (fhandler_base *fh)
210{
8ed5c9b6 211 for (unsigned i = 0; i < farchetype; i++)
8e10c431
CF
212 if (fh == archetypes[i])
213 {
6ae28c22
CF
214 debug_printf ("deleting element %d for %s(%d/%d)", i, fh->get_name (),
215 fh->dev ().get_major (), fh->dev ().get_minor ());
8e10c431
CF
216 if (i < --farchetype)
217 archetypes[i] = archetypes[farchetype];
218 break;
219 }
220
221 delete fh;
222}
223
1fd5e000 224int
499494d2 225dtable::find_unused_handle (size_t start)
1fd5e000 226{
09244c00 227 /* When extending, try to allocate a NOFILE_INCR chunk
9915ebec
CF
228 following the empty fd. */
229 size_t extendby = NOFILE_INCR + ((start >= size) ? 1 + start - size : 0);
f456b9f6 230
499494d2 231 /* This do loop should only ever execute twice. */
f456b9f6 232 int res = -1;
1fd5e000
CF
233 do
234 {
e773b7cf 235 for (size_t i = start; i < size; i++)
91892f50 236 if (fds[i] == NULL)
f456b9f6
CF
237 {
238 res = (int) i;
9262c055 239 goto out;
f456b9f6 240 }
1fd5e000 241 }
09244c00 242 while (extend (extendby, start));
9262c055 243out:
f456b9f6 244 return res;
1fd5e000
CF
245}
246
0646a508 247void
9015e0fb 248dtable::release (int fd)
1fd5e000 249{
0646a508
CF
250 if (fds[fd]->need_fixup_before ())
251 dec_need_fixup_before ();
3143cb7c 252 fds[fd]->dec_refcnt ();
0646a508 253 fds[fd] = NULL;
30fa1549
CF
254 if (fd <= 2)
255 set_std_handle (fd);
1fd5e000
CF
256}
257
45586380 258extern "C" int
ebd645e7
CF
259cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
260 DWORD myaccess)
261{
f456b9f6 262 cygheap->fdtab.lock ();
ebd645e7
CF
263 if (fd == -1)
264 fd = cygheap->fdtab.find_unused_handle ();
7ac61736 265 fhandler_base *fh = build_fh_name (name);
e5b7e4d1 266 if (!fh)
f456b9f6
CF
267 fd = -1;
268 else
269 {
270 cygheap->fdtab[fd] = fh;
271 cygheap->fdtab[fd]->inc_refcnt ();
272 fh->init (handle, myaccess, bin ?: fh->pc_binmode ());
273 }
274 cygheap->fdtab.unlock ();
ebd645e7
CF
275 return fd;
276}
277
1fd5e000 278void
54030e21 279dtable::init_std_file_from_handle (int fd, HANDLE handle)
1fd5e000 280{
5e7c84e5 281 tmp_pathbuf tp;
ebd645e7 282 CONSOLE_SCREEN_BUFFER_INFO buf;
ebd645e7 283 DCB dcb;
abb58a6d 284 unsigned bin = O_BINARY;
b2867a68 285 device dev;
ebd645e7
CF
286
287 first_fd_for_open = 0;
1ac6d1a1 288
083abe54
CF
289 if (!not_open (fd))
290 return;
291
cef69559 292 SetLastError (0);
1ffe3e67 293 DWORD access = 0;
cef69559 294 DWORD ft = GetFileType (handle);
5e7c84e5 295 char *name = tp.c_get ();
1ffe3e67 296 name[0] = '\0';
88f0dc31
CF
297 if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE)
298 /* can't figure out what this is */;
299 else if (ft == FILE_TYPE_PIPE)
1fd5e000 300 {
019fc8d8
CV
301 int rcv = 0, len = sizeof (int);
302
88f0dc31 303 if (handle_to_fn (handle, name))
02a33ea7 304 dev.parse (name);
019fc8d8 305 else if (strcmp (name, ":sock:") == 0
02dbd9ae 306 /* NtQueryObject returns an error when called on an LSP socket
859d215b
CV
307 handle. fhandler_socket::set_socket_handle tries to fetch
308 the underlying base socket, but this might fail. */
019fc8d8
CV
309 || (strcmp (name, unknown_file) == 0
310 && !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
311 (char *) &rcv, &len)))
312 {
313 /* socket */
03f380c2 314 dev = *af_inet_dev;
019fc8d8
CV
315 name[0] = '\0';
316 }
1ffe3e67
CF
317 else if (fd == 0)
318 dev = *piper_dev;
4ab6034f 319 else
1ffe3e67 320 dev = *pipew_dev;
4ab6034f 321 }
92ddb742 322 else if (GetConsoleScreenBufferInfo (handle, &buf)
b86f999a 323 || GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
1ffe3e67 324 {
92ddb742 325 /* Console I/O */
13a84ac7 326 if (CTTY_IS_VALID (myself->ctty))
44d2fc0a 327 dev.parse (myself->ctty);
1ffe3e67 328 else
6ae28c22
CF
329 {
330 dev.parse (FH_CONSOLE);
331 CloseHandle (handle);
332 handle = INVALID_HANDLE_VALUE;
333 }
1ffe3e67 334 }
1ffe3e67 335 else if (GetCommState (handle, &dcb))
92ddb742
CF
336 /* FIXME: Not right - assumes ttyS0 */
337 dev.parse (DEV_SERIAL_MAJOR, 0);
1ffe3e67
CF
338 else
339 /* Try to figure it out from context - probably a disk file */
340 handle_to_fn (handle, name);
cef69559 341
1ffe3e67 342 if (!name[0] && !dev)
cef69559
CF
343 fds[fd] = NULL;
344 else
4ab6034f 345 {
7ac61736
CF
346 fhandler_base *fh;
347
348 if (dev)
1ffe3e67 349 fh = build_fh_dev (dev);
7ac61736
CF
350 else
351 fh = build_fh_name (name);
352
e5b7e4d1
CF
353 if (!fh)
354 return;
355
1ffe3e67 356 if (name[0])
abb58a6d 357 {
634a4140
CF
358 bin = fh->pc_binmode ();
359 if (!bin)
360 {
361 bin = fh->get_default_fmode (O_RDWR);
362 if (!bin && dev)
363 bin = O_BINARY;
364 }
abb58a6d 365 }
9655ff26 366
02a33ea7
CV
367 IO_STATUS_BLOCK io;
368 FILE_ACCESS_INFORMATION fai;
6ae28c22 369 int openflags = O_BINARY;
02a33ea7 370
1091d440 371 /* Console windows are no kernel objects up to Windows 7/2008R2, so the
d2ef2331 372 access mask returned by NtQueryInformationFile is meaningless. CMD
1091d440
CV
373 always hands down stdin handles as R/O handles, but our tty slave
374 sides are R/W. */
06f46dc3 375 if (fh->is_tty ())
6ae28c22
CF
376 {
377 openflags |= O_RDWR;
378 access |= GENERIC_READ | GENERIC_WRITE;
379 }
380 else if (!iscons_dev (dev)
381 && NT_SUCCESS (NtQueryInformationFile (handle, &io, &fai,
382 sizeof fai,
383 FileAccessInformation)))
02a33ea7 384 {
02a33ea7 385 if (fai.AccessFlags & FILE_WRITE_DATA)
6ae28c22
CF
386 {
387 openflags |= O_WRONLY;
388 access |= GENERIC_WRITE;
389 }
390 if (fai.AccessFlags & FILE_READ_DATA)
391 {
392 openflags |= openflags & O_WRONLY ? O_RDWR : O_RDONLY;
393 access |= GENERIC_READ;
394 }
02a33ea7 395 }
4248960e 396 else if (fd == 0)
6ae28c22
CF
397 {
398 openflags |= O_RDONLY;
399 access |= GENERIC_READ;
400 }
70300fdb 401 else
6ae28c22
CF
402 {
403 openflags |= O_WRONLY;
404 access |= GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
405 possible for some versions of handles */
406 }
407 if (!fh->init (handle, access, bin))
3c4f2024 408 api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ());
99be2383
KB
409 if (fh->ispipe ())
410 {
411 fhandler_pipe *fhp = (fhandler_pipe *) fh;
412 fhp->set_pipe_buf_size ();
90788821
TY
413 /* Set read pipe always to nonblocking */
414 fhp->set_pipe_non_blocking (fhp->get_device () == FH_PIPER ?
415 true : fhp->is_nonblocking ());
99be2383 416 }
1ae0a7c5 417
be08c5c4
KB
418 if (!fh->open_setup (openflags))
419 api_fatal ("open_setup failed, %E");
6ae28c22 420 fh->usecount = 0;
1ae0a7c5 421 cygheap->fdtab[fd] = fh;
3143cb7c 422 cygheap->fdtab[fd]->inc_refcnt ();
1ae0a7c5 423 set_std_handle (fd);
cef69559 424 paranoid_printf ("fd %d, handle %p", fd, handle);
2cab4d0b 425 fh->post_open_setup (fd);
1fd5e000 426 }
1fd5e000
CF
427}
428
3d938be6
CV
429#define cnew(name, ...) \
430 ({ \
431 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
c38da4ee 432 ptr ? new (ptr) name (__VA_ARGS__) : NULL; \
3d938be6 433 })
1ffe3e67 434
23771fa1
CF
435#define cnew_no_ctor(name, ...) \
436 ({ \
437 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
438 ptr ? new (ptr) name (ptr) : NULL; \
439 })
440
4ee93264
CV
441fhandler_base *
442build_fh_name (const char *name, unsigned opt, suffix_info *si)
1fd5e000 443{
4ee93264 444 path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
4ab6034f
CF
445 if (pc.error)
446 {
3d938be6
CV
447 fhandler_base *fh = cnew (fhandler_nodevice);
448 if (fh)
6a7bea70
CF
449 fh->set_error (pc.error);
450 set_errno (fh ? pc.error : EMFILE);
e00700cd 451 return fh;
1fd5e000
CF
452 }
453
7ac61736 454 return build_fh_pc (pc);
1fd5e000
CF
455}
456
457fhandler_base *
7ac61736 458build_fh_dev (const device& dev, const char *unix_name)
ff938546 459{
7ac61736 460 path_conv pc (dev);
7ac61736 461 if (unix_name)
d2bd82aa 462 pc.set_posix (unix_name);
7ac61736 463 else
b2867a68 464 pc.set_posix (dev.name ());
7ac61736 465 return build_fh_pc (pc);
ff938546
CF
466}
467
6a7bea70 468#define fh_unset ((fhandler_base *) 1)
6ae28c22
CF
469static device last_tty_dev;
470#define fh_last_tty_dev ((fhandler_termios *) cygheap->fdtab.find_archetype (last_tty_dev))
23771fa1 471
92ddb742 472static fhandler_base *
23771fa1 473fh_alloc (path_conv& pc)
1fd5e000 474{
6a7bea70 475 fhandler_base *fh = fh_unset;
23771fa1 476 fhandler_base *fhraw = NULL;
1fd5e000 477
23771fa1 478 switch (pc.dev.get_major ())
7b02cb30 479 {
38d732a1 480 case DEV_PTYS_MAJOR:
23771fa1
CF
481 fh = cnew (fhandler_pty_slave, pc.dev.get_minor ());
482 break;
38d732a1 483 case DEV_PTYM_MAJOR:
23771fa1 484 fh = cnew (fhandler_pty_master, pc.dev.get_minor ());
7b02cb30 485 break;
7b02cb30
CF
486 case DEV_FLOPPY_MAJOR:
487 case DEV_CDROM_MAJOR:
488 case DEV_SD_MAJOR:
b2867a68
CV
489 case DEV_SD1_MAJOR ... DEV_SD7_MAJOR:
490 case DEV_SD_HIGHPART_START ... DEV_SD_HIGHPART_END:
3d938be6 491 fh = cnew (fhandler_dev_floppy);
7b02cb30
CF
492 break;
493 case DEV_TAPE_MAJOR:
3d938be6 494 fh = cnew (fhandler_dev_tape);
7b02cb30
CF
495 break;
496 case DEV_SERIAL_MAJOR:
3d938be6 497 fh = cnew (fhandler_serial);
7b02cb30 498 break;
44d2fc0a 499 case DEV_CONS_MAJOR:
23771fa1 500 fh = cnew (fhandler_console, pc.dev);
44d2fc0a 501 break;
7b02cb30 502 default:
61522196 503 switch ((dev_t) pc.dev)
7b02cb30
CF
504 {
505 case FH_CONSOLE:
506 case FH_CONIN:
507 case FH_CONOUT:
23771fa1 508 fh = cnew (fhandler_console, pc.dev);
7b02cb30 509 break;
23771fa1
CF
510 case FH_PTMX:
511 if (pc.isopen ())
b03601a6 512 fh = cnew (fhandler_pty_master, -1, (dev_t) pc.dev);
23771fa1 513 else
1b23b30b 514 fhraw = cnew_no_ctor (fhandler_pty_master, -1);
7b02cb30
CF
515 break;
516 case FH_WINDOWS:
3d938be6 517 fh = cnew (fhandler_windows);
7b02cb30
CF
518 break;
519 case FH_FIFO:
3d938be6 520 fh = cnew (fhandler_fifo);
7b02cb30
CF
521 break;
522 case FH_PIPE:
523 case FH_PIPER:
524 case FH_PIPEW:
3d938be6 525 fh = cnew (fhandler_pipe);
7b02cb30 526 break;
03f380c2 527 case FH_INET:
859d215b
CV
528 fh = cnew (fhandler_socket_inet);
529 break;
03f380c2 530 case FH_LOCAL:
859d215b 531 fh = cnew (fhandler_socket_local);
7b02cb30 532 break;
6c55be9d 533#ifdef __WITH_AF_UNIX
7f7532fa
CV
534 case FH_UNIX:
535 fh = cnew (fhandler_socket_unix);
536 break;
6c55be9d 537#endif /* __WITH_AF_UNIX */
7b02cb30 538 case FH_FS:
3d938be6 539 fh = cnew (fhandler_disk_file);
7b02cb30
CF
540 break;
541 case FH_NULL:
3d938be6 542 fh = cnew (fhandler_dev_null);
7b02cb30
CF
543 break;
544 case FH_ZERO:
545 case FH_FULL:
3d938be6 546 fh = cnew (fhandler_dev_zero);
7b02cb30
CF
547 break;
548 case FH_RANDOM:
549 case FH_URANDOM:
3d938be6 550 fh = cnew (fhandler_dev_random);
7b02cb30 551 break;
7b02cb30 552 case FH_CLIPBOARD:
3d938be6 553 fh = cnew (fhandler_dev_clipboard);
7b02cb30 554 break;
2a4af366
TY
555 case FH_OSS_MIXER:
556 fh = cnew (fhandler_dev_mixer);
557 break;
7b02cb30 558 case FH_OSS_DSP:
3d938be6 559 fh = cnew (fhandler_dev_dsp);
7b02cb30
CF
560 break;
561 case FH_PROC:
3d938be6 562 fh = cnew (fhandler_proc);
7b02cb30
CF
563 break;
564 case FH_REGISTRY:
3d938be6 565 fh = cnew (fhandler_registry);
7b02cb30
CF
566 break;
567 case FH_PROCESS:
3d938be6 568 fh = cnew (fhandler_process);
7b02cb30 569 break;
7aca27b4
CV
570 case FH_PROCESSFD:
571 fh = cnew (fhandler_process_fd);
572 break;
96d7dee2 573 case FH_PROCNET:
3d938be6 574 fh = cnew (fhandler_procnet);
96d7dee2 575 break;
43f65cdd 576 case FH_PROCSYS:
3d938be6 577 fh = cnew (fhandler_procsys);
43f65cdd 578 break;
d68288f6 579 case FH_PROCSYSVIPC:
3d938be6 580 fh = cnew (fhandler_procsysvipc);
d68288f6 581 break;
7b02cb30 582 case FH_NETDRIVE:
3d938be6 583 fh = cnew (fhandler_netdrive);
7b02cb30 584 break;
1f312200
CV
585 case FH_DEV:
586 fh = cnew (fhandler_dev);
587 break;
c8cf1933
CF
588 case FH_DEV_DISK:
589 fh = cnew (fhandler_dev_disk);
590 break;
4ec08891
JS
591 case FH_DEV_FD:
592 fh = cnew (fhandler_dev_fd);
593 break;
f7c8c454
CV
594 case FH_CYGDRIVE:
595 fh = cnew (fhandler_cygdrive);
596 break;
9d13a299
CV
597 case FH_SIGNALFD:
598 fh = cnew (fhandler_signalfd);
599 break;
068182e2
CV
600 case FH_TIMERFD:
601 fh = cnew (fhandler_timerfd);
602 break;
4fc922b2
CV
603 case FH_MQUEUE:
604 fh = cnew (fhandler_mqueue);
605 break;
7b02cb30 606 case FH_TTY:
23771fa1 607 if (!pc.isopen ())
38d732a1 608 {
3edb55af
TY
609 if (CTTY_IS_VALID (myself->ctty))
610 {
611 if (iscons_dev (myself->ctty))
612 fhraw = cnew_no_ctor (fhandler_console, -1);
613 else
614 fhraw = cnew_no_ctor (fhandler_pty_slave, -1);
615 }
6ae28c22
CF
616 debug_printf ("not called from open for /dev/tty");
617 }
13a84ac7 618 else if (!CTTY_IS_VALID (myself->ctty) && last_tty_dev
6ae28c22
CF
619 && !myself->set_ctty (fh_last_tty_dev, 0))
620 debug_printf ("no /dev/tty assigned");
13a84ac7 621 else if (CTTY_IS_VALID (myself->ctty))
6ae28c22
CF
622 {
623 debug_printf ("determining /dev/tty assignment for ctty %p", myself->ctty);
38d732a1
CF
624 if (iscons_dev (myself->ctty))
625 fh = cnew (fhandler_console, pc.dev);
626 else
b03601a6
TY
627 fh = cnew (fhandler_pty_slave,
628 minor (myself->ctty), (dev_t) pc.dev);
6ae28c22
CF
629 if (fh->dev () != FH_NADA)
630 fh->set_name ("/dev/tty");
38d732a1 631 }
23771fa1 632 break;
0e1ba888 633 }
7b02cb30 634 }
7ac61736 635
23771fa1
CF
636 /* If `fhraw' is set that means that this fhandler is just a dummy
637 set up for stat(). Mock it up for use by stat without actually
638 trying to do any real initialization. */
639 if (fhraw)
640 {
641 fh = fhraw;
642 fh->set_name (pc);
643 if (fh->use_archetype ())
644 fh->archetype = fh;
645 }
2e82c935 646 if (fh == fh_unset)
3d938be6 647 fh = cnew (fhandler_nodevice);
23771fa1
CF
648 else if (fh->dev () == FH_ERROR)
649 {
8b4bd082 650 if (!pc.isopen () && pc.dev.isfs ())
080f275b 651 fh->dev () = pc.dev; /* Special case: This file actually exists on
8b4bd082
CF
652 disk and we're not trying to open it so just
653 return the info from pc. */
080f275b
CF
654 else
655 {
656 delete fh;
657 fh = NULL;
658 }
23771fa1 659 }
92ddb742
CF
660 return fh;
661}
662
663fhandler_base *
6ae28c22 664build_fh_pc (path_conv& pc)
92ddb742 665{
23771fa1 666 fhandler_base *fh = fh_alloc (pc);
2e82c935 667
1c1b04b8 668 if (!fh)
9e1fd6bc 669 {
23771fa1 670 set_errno (ENXIO);
9e1fd6bc
CV
671 goto out;
672 }
7ac61736 673
92ddb742 674 if (!fh->use_archetype ())
6ae28c22 675 fh->set_name (pc);
92ddb742 676 else if ((fh->archetype = cygheap->fdtab.find_archetype (fh->dev ())))
6ae28c22
CF
677 {
678 debug_printf ("found an archetype for %s(%d/%d) io_handle %p", fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor (),
a9c661a9 679 fh->archetype->get_handle ());
6ae28c22 680 if (!fh->get_name ())
b2867a68 681 fh->set_name (fh->archetype->dev ().name ());
6ae28c22
CF
682 }
683 else if (cygwin_finished_initializing && !pc.isopen ())
684 fh->set_name (pc);
92ddb742
CF
685 else
686 {
6ae28c22 687 if (!fh->get_name ())
b2867a68 688 fh->set_name (fh->dev ().native ());
23771fa1
CF
689 fh->archetype = fh->clone ();
690 debug_printf ("created an archetype (%p) for %s(%d/%d)", fh->archetype, fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor ());
92ddb742
CF
691 fh->archetype->archetype = NULL;
692 *cygheap->fdtab.add_archetype () = fh->archetype;
693 }
694
6ae28c22
CF
695
696 /* Keep track of the last tty-like thing opened. We could potentially want
697 to open it if /dev/tty is referenced. */
13a84ac7 698 if (CTTY_IS_VALID (myself->ctty) || !fh->is_tty () || !pc.isctty_capable ())
6ae28c22
CF
699 last_tty_dev = FH_NADA;
700 else
701 last_tty_dev = fh->dev ();
23771fa1 702
c3a9063f 703out:
61522196 704 debug_printf ("fh %p, dev %08x", fh, fh ? (dev_t) fh->dev () : 0);
7ac61736 705 return fh;
1fd5e000
CF
706}
707
708fhandler_base *
e70fdfb9 709dtable::dup_worker (fhandler_base *oldfh, int flags)
1fd5e000 710{
23771fa1 711 fhandler_base *newfh = oldfh->clone ();
6a7bea70 712 if (!newfh)
b6624e23 713 debug_printf ("clone failed");
6a7bea70 714 else
1fd5e000 715 {
92ddb742 716 if (!oldfh->archetype)
a9c661a9 717 newfh->set_handle (NULL);
23771fa1 718
5f0913df 719 newfh->pc.close_conv_handle ();
23771fa1 720 if (oldfh->dup (newfh, flags))
6a7bea70 721 {
1c1b04b8
CV
722 delete newfh;
723 newfh = NULL;
6a7bea70
CF
724 debug_printf ("oldfh->dup failed");
725 }
726 else
727 {
8fa8b3a3
CF
728 /* Don't increment refcnt here since we don't know if this is a
729 allocated fd. So we leave this chore to the caller. */
730
92ddb742
CF
731 newfh->usecount = 0;
732 newfh->archetype_usecount (1);
8fa8b3a3 733
e70fdfb9 734 /* The O_CLOEXEC flag enforces close-on-exec behaviour. */
92ddb742 735 newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
4eb5175d 736 debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
a9c661a9 737 oldfh->get_handle (), newfh->get_handle ());
6a7bea70 738 }
1fd5e000 739 }
1fd5e000
CF
740 return newfh;
741}
742
743int
e70fdfb9 744dtable::dup3 (int oldfd, int newfd, int flags)
1fd5e000
CF
745{
746 int res = -1;
747 fhandler_base *newfh = NULL; // = NULL to avoid an incorrect warning
748
61522196 749 debug_printf ("dup3 (%d, %d, %y)", oldfd, newfd, flags);
2d1d1eb1 750 lock ();
3143cb7c 751 bool do_unlock = true;
b9c61a8d
CF
752 bool unlock_on_return;
753 if (!(flags & O_EXCL))
754 unlock_on_return = true; /* Relinquish lock on return */
755 else
756 {
757 flags &= ~O_EXCL;
758 unlock_on_return = false; /* Return with lock set on success */
759 }
1fd5e000
CF
760
761 if (not_open (oldfd))
762 {
5a449743 763 syscall_printf ("fd %d not open", oldfd);
1fd5e000
CF
764 set_errno (EBADF);
765 goto done;
766 }
5b8358e6 767 if (newfd >= OPEN_MAX || newfd < 0)
4c78be52
CF
768 {
769 syscall_printf ("new fd out of bounds: %d", newfd);
770 set_errno (EBADF);
771 goto done;
772 }
e70fdfb9 773 if ((flags & ~O_CLOEXEC) != 0)
1fd5e000 774 {
61522196 775 syscall_printf ("invalid flags value %y", flags);
e70fdfb9
CV
776 set_errno (EINVAL);
777 return -1;
1fd5e000
CF
778 }
779
e70fdfb9 780 if ((newfh = dup_worker (fds[oldfd], flags)) == NULL)
1fd5e000
CF
781 {
782 res = -1;
783 goto done;
784 }
785
a9934559 786 debug_printf ("newfh->io_handle %p, oldfh->io_handle %p, new win32_name %p, old win32_name %p",
a9c661a9 787 newfh->get_handle (), fds[oldfd]->get_handle (), newfh->get_win32_name (), fds[oldfd]->get_win32_name ());
b0e82b74 788
4c78be52 789 if (!not_open (newfd))
5ec14fe4 790 close (newfd);
3a4ce731 791 else if ((size_t) newfd >= size
8fa8b3a3
CF
792 && find_unused_handle (newfd) < 0)
793 /* couldn't extend fdtab */
5a449743 794 {
4c78be52
CF
795 newfh->close ();
796 res = -1;
5a449743
CF
797 goto done;
798 }
b0e82b74 799
1fd5e000 800 fds[newfd] = newfh;
dd4f0b23 801
1fd5e000
CF
802 if ((res = newfd) <= 2)
803 set_std_handle (res);
b9c61a8d 804 do_unlock = unlock_on_return;
1fd5e000 805
1fd5e000 806done:
3143cb7c
CF
807 if (do_unlock)
808 unlock ();
61522196 809 syscall_printf ("%R = dup3(%d, %d, %y)", res, oldfd, newfd, flags);
1fd5e000
CF
810
811 return res;
812}
813
b4fa8164
CF
814bool
815dtable::select_read (int fd, select_stuff *ss)
1fd5e000 816{
b0e82b74 817 if (not_open (fd))
1fd5e000
CF
818 {
819 set_errno (EBADF);
b4fa8164 820 return false;
1fd5e000 821 }
b0e82b74 822 fhandler_base *fh = fds[fd];
b4fa8164 823 select_record *s = fh->select_read (ss);
1fd5e000 824 s->fd = fd;
c7ef20e7
CF
825 if (!s->fh)
826 s->fh = fh;
169c465a 827 s->thread_errno = 0;
1fd5e000 828 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 829 return true;
1fd5e000
CF
830}
831
b4fa8164
CF
832bool
833dtable::select_write (int fd, select_stuff *ss)
1fd5e000 834{
b0e82b74 835 if (not_open (fd))
1fd5e000
CF
836 {
837 set_errno (EBADF);
838 return NULL;
839 }
b0e82b74 840 fhandler_base *fh = fds[fd];
b4fa8164 841 select_record *s = fh->select_write (ss);
1fd5e000
CF
842 s->fd = fd;
843 s->fh = fh;
169c465a 844 s->thread_errno = 0;
106e3acf 845 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 846 return true;
1fd5e000
CF
847}
848
b4fa8164
CF
849bool
850dtable::select_except (int fd, select_stuff *ss)
1fd5e000 851{
b0e82b74 852 if (not_open (fd))
1fd5e000
CF
853 {
854 set_errno (EBADF);
855 return NULL;
856 }
b0e82b74 857 fhandler_base *fh = fds[fd];
b4fa8164 858 select_record *s = fh->select_except (ss);
1fd5e000
CF
859 s->fd = fd;
860 s->fh = fh;
169c465a 861 s->thread_errno = 0;
1fd5e000 862 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 863 return true;
1fd5e000
CF
864}
865
c16548b2
CF
866void
867dtable::move_fd (int from, int to)
868{
869 // close (to); /* It is assumed that this is close-on-exec */
870 fds[to] = fds[from];
871 fds[from] = NULL;
872}
873
fef1edbc
CF
874void
875dtable::set_file_pointers_for_exec ()
876{
cce64750
CV
877/* This is not POSIX-compliant so the function is only called for
878 non-Cygwin processes. */
0be0b8f0
CV
879 LARGE_INTEGER eof = { QuadPart: 0 };
880
2d1d1eb1 881 lock ();
fef1edbc
CF
882 fhandler_base *fh;
883 for (size_t i = 0; i < size; i++)
884 if ((fh = fds[i]) != NULL && fh->get_flags () & O_APPEND)
0be0b8f0 885 SetFilePointerEx (fh->get_handle (), eof, NULL, FILE_END);
2d1d1eb1 886 unlock ();
fef1edbc
CF
887}
888
881beea8
CF
889void
890dtable::fixup_close (size_t i, fhandler_base *fh)
891{
892 if (fh->archetype)
893 {
894 debug_printf ("closing fd %d since it is an archetype", i);
895 fh->close_with_arch ();
896 }
897 release (i);
898}
899
b0e82b74 900void
52806019 901dtable::fixup_after_exec ()
1fd5e000 902{
b0e82b74 903 first_fd_for_open = 0;
2e78b61d 904 fhandler_base *fh;
b0e82b74 905 for (size_t i = 0; i < size; i++)
2e78b61d 906 if ((fh = fds[i]) != NULL)
4f7ac76a 907 {
2e78b61d 908 fh->clear_readahead ();
59297e04 909 fh->fixup_after_exec ();
881beea8
CF
910 /* Close the handle if it's close-on-exec or if an error was detected
911 (typically with opening a console in a gui app) by fixup_after_exec.
912 */
a9c661a9 913 if (fh->close_on_exec () || (!fh->nohandle () && !fh->get_handle ()))
881beea8 914 fixup_close (i, fh);
421ba492
CF
915 else if (fh->get_popen_pid ())
916 close (i);
59297e04 917 else if (i == 0)
a9c661a9 918 SetStdHandle (std_consts[i], fh->get_handle ());
59297e04
CF
919 else if (i <= 2)
920 SetStdHandle (std_consts[i], fh->get_output_handle ());
4f7ac76a 921 }
523985b3
TY
922 if (cygheap->ctty)
923 cygheap->ctty->fixup_after_exec ();
1fd5e000
CF
924}
925
926void
9015e0fb 927dtable::fixup_after_fork (HANDLE parent)
1fd5e000 928{
b0e82b74 929 fhandler_base *fh;
1fd5e000 930 for (size_t i = 0; i < size; i++)
b0e82b74 931 if ((fh = fds[i]) != NULL)
1fd5e000 932 {
56551a9b 933 if (fh->close_on_exec () || fh->need_fork_fixup ())
1fd5e000 934 {
c729f227 935 debug_printf ("fd %d (%s)", i, fh->get_name ());
1fd5e000 936 fh->fixup_after_fork (parent);
a9c661a9 937 if (!fh->nohandle () && !fh->get_handle ())
881beea8
CF
938 {
939 /* This should actually never happen but it's here to make sure
940 we don't crash due to access of an unopened file handle. */
941 fixup_close (i, fh);
942 continue;
943 }
1fd5e000 944 }
f3acbe3e 945 if (i == 0)
a9c661a9 946 SetStdHandle (std_consts[i], fh->get_handle ());
f3acbe3e
CF
947 else if (i <= 2)
948 SetStdHandle (std_consts[i], fh->get_output_handle ());
1fd5e000 949 }
523985b3
TY
950
951 if (cygheap->ctty)
952 cygheap->ctty->fixup_after_fork (parent);
1fd5e000
CF
953}
954
88f0dc31
CF
955static void
956decode_tty (char *buf, WCHAR *w32)
1ffe3e67
CF
957{
958 int ttyn = wcstol (w32, NULL, 10);
92601445 959 __ptsname (buf, ttyn);
1ffe3e67
CF
960}
961
88f0dc31
CF
962/* Try to derive posix filename from given handle. Return true if
963 the handle is associated with a cygwin tty. */
964static bool
2402700d
CF
965handle_to_fn (HANDLE h, char *posix_fn)
966{
ab5d348d 967 tmp_pathbuf tp;
1ffe3e67 968 ULONG len = 0;
1ffe3e67 969 WCHAR *maxmatchdos = NULL;
5e7c84e5 970 PWCHAR device = tp.w_get ();
1ffe3e67 971 int maxmatchlen = 0;
019fc8d8
CV
972 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) tp.w_get ();
973
974 NTSTATUS status = NtQueryObject (h, ObjectNameInformation, ntfn, 65536, &len);
975 if (!NT_SUCCESS (status))
61522196 976 debug_printf ("NtQueryObject failed, %y", status);
019fc8d8
CV
977 // NT seems to do this on an unopened file
978 else if (!ntfn->Name.Buffer)
979 debug_printf ("nt->Name.Buffer == NULL");
7b9e380f 980 else
1ffe3e67 981 {
019fc8d8
CV
982 WCHAR *w32 = ntfn->Name.Buffer;
983 size_t w32len = ntfn->Name.Length / sizeof (WCHAR);
984 w32[w32len] = L'\0';
2bb6b3e5 985
019fc8d8
CV
986 if (wcscasecmp (w32, DEV_NULL) == 0)
987 {
988 strcpy (posix_fn, "/dev/null");
989 return false;
990 }
2bb6b3e5 991
019fc8d8
CV
992 if (wcscasecmp (w32, DEV_SOCKET) == 0)
993 {
994 strcpy (posix_fn, ":sock:");
995 return false;
996 }
2402700d 997
019fc8d8
CV
998 if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0)
999 {
1000 w32 += DEV_NAMED_PIPE_LEN;
1001 if (wcsncmp (w32, L"cygwin-", WCLEN (L"cygwin-")) != 0)
1002 return false;
1003 w32 += WCLEN (L"cygwin-");
526b0fbc 1004 /* Check for installation key and trailing dash. */
8895d962
CV
1005 w32len = cygheap->installation_key.Length / sizeof (WCHAR);
1006 if (w32len
1007 && wcsncmp (w32, cygheap->installation_key.Buffer, w32len) != 0)
526b0fbc
CV
1008 return false;
1009 w32 += w32len;
1010 if (*w32 != L'-')
1011 return false;
1012 ++w32;
2ae8e0e4 1013 bool istty = wcsncmp (w32, L"pty", WCLEN (L"pty")) == 0;
019fc8d8 1014 if (istty)
2ae8e0e4 1015 decode_tty (posix_fn, w32 + WCLEN (L"pty"));
019fc8d8
CV
1016 else if (wcsncmp (w32, L"pipe", WCLEN (L"pipe")) == 0)
1017 strcpy (posix_fn, "/dev/pipe");
1018 return istty;
1019 }
5bf785a0 1020
019fc8d8
CV
1021 WCHAR fnbuf[64 * 1024];
1022 if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
9c36b394 1023 || !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf) / sizeof (WCHAR)))
019fc8d8
CV
1024 {
1025 sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
1026 return false;
1027 }
2402700d 1028
019fc8d8
CV
1029 for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1)
1030 {
5e7c84e5 1031 if (!QueryDosDeviceW (s, device, NT_MAX_PATH))
019fc8d8
CV
1032 continue;
1033 if (wcschr (s, ':') == NULL)
1034 continue;
1035 WCHAR *q = wcsrchr (device, ';');
1036 if (q)
7b9e380f 1037 {
019fc8d8
CV
1038 WCHAR *r = wcschr (q, '\\');
1039 if (r)
1040 wcscpy (q, r + 1);
7b9e380f 1041 }
019fc8d8
CV
1042 int devlen = wcslen (device);
1043 if (device[devlen - 1] == L'\\')
1044 device[--devlen] = L'\0';
1045 if (devlen < maxmatchlen)
1046 continue;
1047 if (wcsncmp (device, w32, devlen) != 0||
1048 (w32[devlen] != L'\0' && w32[devlen] != L'\\'))
1049 continue;
1050 maxmatchlen = devlen;
1051 maxmatchdos = s;
1052 debug_printf ("current match '%W' = '%W'\n", s, device);
1053 }
1ffe3e67 1054
019fc8d8
CV
1055 if (maxmatchlen)
1056 {
1057 WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\');
1058 size_t n = wcslen (maxmatchdos);
1059 WCHAR ch;
1060 if (!p)
1061 ch = L'\0';
1062 else
7b9e380f 1063 {
019fc8d8
CV
1064 if (maxmatchdos[n - 1] == L'\\')
1065 n--;
1066 w32 += maxmatchlen - n;
1067 ch = L'\\';
7b9e380f 1068 }
019fc8d8
CV
1069 memcpy (w32, maxmatchdos, n * sizeof (WCHAR));
1070 w32[n] = ch;
1071 }
1072 else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0)
1073 {
1074 w32 += DEV_REMOTE_LEN - 2;
1075 *w32 = L'\\';
1076 debug_printf ("remote drive");
1077 }
1078 else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0)
1079 {
1080 w32 += DEV_REMOTE1_LEN - 2;
1081 *w32 = L'\\';
1082 debug_printf ("remote drive");
1083 }
1ffe3e67 1084
019fc8d8
CV
1085 cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
1086 NT_MAX_PATH);
37be5a67 1087
019fc8d8
CV
1088 debug_printf ("derived path '%W', posix '%s'", w32, posix_fn);
1089 return false;
634a4140 1090 }
2402700d 1091
1ffe3e67 1092 strcpy (posix_fn, unknown_file);
88f0dc31 1093 return false;
2402700d 1094}
b14f53a8
CV
1095
1096void
1097dtable::fixup_before_fork (DWORD target_proc_id)
1098{
1099 lock ();
1100 fhandler_base *fh;
1101 for (size_t i = 0; i < size; i++)
1102 if ((fh = fds[i]) != NULL)
1103 {
b86f999a
CF
1104 debug_printf ("fd %d (%s)", i, fh->get_name ());
1105 fh->fixup_before_fork_exec (target_proc_id);
b14f53a8
CV
1106 }
1107 unlock ();
b86f999a
CF
1108}
1109
b14f53a8
CV
1110void
1111dtable::fixup_before_exec (DWORD target_proc_id)
1112{
1113 lock ();
1114 fhandler_base *fh;
1115 for (size_t i = 0; i < size; i++)
1116 if ((fh = fds[i]) != NULL && !fh->close_on_exec ())
1117 {
b86f999a
CF
1118 debug_printf ("fd %d (%s)", i, fh->get_name ());
1119 fh->fixup_before_fork_exec (target_proc_id);
b14f53a8
CV
1120 }
1121 unlock ();
b86f999a 1122}
This page took 0.737622 seconds and 6 git commands to generate.