]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/external.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / external.cc
CommitLineData
1fd5e000
CF
1/* external.cc: Interface to Cygwin internals from external programs.
2
bc837d22
CF
3 Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4 2008, 2009, 2010, 2011, 2012 Red Hat, Inc.
1fd5e000
CF
5
6 Written by Christopher Faylor <cgf@cygnus.com>
7
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
14#include "winsup.h"
bccd5e0d 15#include "sigproc.h"
e2ebe117 16#include "pinfo.h"
29ac7f89 17#include "shared_info.h"
f0338f54 18#include "cygwin_version.h"
a9f20457 19#include "cygerrno.h"
a9f20457 20#include "path.h"
7ac61736 21#include "fhandler.h"
a9f20457
CF
22#include "dtable.h"
23#include "cygheap.h"
494a66d9 24#include "heap.h"
29d52c8a 25#include "cygtls.h"
1cd8ccec 26#include "child_info.h"
6577c186 27#include "environ.h"
51303cbd 28#include "cygserver_setpwd.h"
f90e23f2 29#include <unistd.h>
6577c186 30#include <stdlib.h>
752b16ce 31#include <wchar.h>
b5488135 32#include <iptypes.h>
1fd5e000 33
1cd8ccec 34child_info *get_cygwin_startup_info ();
c8ee587a 35static void exit_process (UINT, bool) __attribute__((noreturn));
b1d9a0bd 36
ac437c3e
CF
37static winpids pids;
38
1fd5e000 39static external_pinfo *
84c7d409 40fillout_pinfo (pid_t pid, int winpid)
1fd5e000
CF
41{
42 BOOL nextpid;
1fd5e000 43 static external_pinfo ep;
9d342d56 44 static char ep_progname_long_buf[NT_MAX_PATH];
1fd5e000
CF
45
46 if ((nextpid = !!(pid & CW_NEXTPID)))
47 pid ^= CW_NEXTPID;
84c7d409 48
84c7d409 49
2c774ac3 50 static unsigned int i;
858f5249 51 if (!pids.npids || !nextpid)
2c774ac3 52 {
883bbc64 53 pids.set (winpid);
2c774ac3
CF
54 i = 0;
55 }
84c7d409 56
3c2c3745
CF
57 if (!pid)
58 i = 0;
59
84c7d409 60 memset (&ep, 0, sizeof ep);
0c9ae85d 61 while (i < pids.npids)
1fd5e000 62 {
0c9ae85d
CF
63 DWORD thispid = pids.winpid (i);
64 _pinfo *p = pids[i];
65 i++;
84c7d409 66
3c2c3745
CF
67 if (!p)
68 {
0c9ae85d 69 if (!nextpid && thispid != (DWORD) pid)
3c2c3745 70 continue;
c3a245f5
CF
71 ep.pid = cygwin_pid (thispid);
72 ep.dwProcessId = thispid;
3c2c3745
CF
73 ep.process_state = PID_IN_USE;
74 ep.ctty = -1;
00a74961 75 break;
3c2c3745 76 }
00a74961 77 else if (nextpid || p->pid == pid || (winpid && thispid == (DWORD) pid))
1fd5e000 78 {
be9b5aba 79 ep.ctty = (p->ctty < 0 || iscons_dev (p->ctty)) ? p->ctty : device::minor (p->ctty);
3c2c3745
CF
80 ep.pid = p->pid;
81 ep.ppid = p->ppid;
3c2c3745
CF
82 ep.dwProcessId = p->dwProcessId;
83 ep.uid = p->uid;
84 ep.gid = p->gid;
85 ep.pgid = p->pgid;
86 ep.sid = p->sid;
a4785603 87 ep.umask = 0;
3c2c3745
CF
88 ep.start_time = p->start_time;
89 ep.rusage_self = p->rusage_self;
90 ep.rusage_children = p->rusage_children;
36093cfb 91 ep.progname[0] = '\0';
d3258e06 92 sys_wcstombs(ep.progname, MAX_PATH, p->progname);
3c2c3745 93 ep.strace_mask = 0;
186637a5 94 ep.version = EXTERNAL_PINFO_VERSION;
3c2c3745
CF
95
96 ep.process_state = p->process_state;
a8d7ae61
CV
97
98 ep.uid32 = p->uid;
99 ep.gid32 = p->gid;
36093cfb 100
9d342d56 101 ep.progname_long = ep_progname_long_buf;
8ae61a8d 102 mount_table->conv_to_posix_path (p->progname, ep.progname_long, 0);
00a74961 103 break;
1fd5e000
CF
104 }
105 }
106
84c7d409
CF
107 if (!ep.pid)
108 {
3c2c3745 109 i = 0;
84c7d409 110 pids.reset ();
fb348d22 111 return NULL;
84c7d409 112 }
1fd5e000
CF
113 return &ep;
114}
115
61522196 116static inline uintptr_t
9bc846bd 117get_cygdrive_info (char *user, char *system, char *user_flags,
1ff9f4b9 118 char *system_flags)
637f5ce0 119{
2a6fc028
CF
120 int res = mount_table->get_cygdrive_info (user, system, user_flags,
121 system_flags);
637f5ce0
CF
122 return (res == ERROR_SUCCESS) ? 1 : 0;
123}
124
61522196 125static bool
5a4a19b3
CV
126check_ntsec (const char *filename)
127{
d5292d66 128 if (!filename)
e2406d71 129 return true;
5a4a19b3 130 path_conv pc (filename);
e2406d71 131 return pc.has_acls ();
5a4a19b3
CV
132}
133
6577c186 134/* Copy cygwin environment variables to the Windows environment. */
8dfce03b
CV
135static PWCHAR
136create_winenv (const char * const *env)
6577c186 137{
9a08fd5a 138 int unused_envc;
752b16ce 139 PWCHAR envblock = NULL;
8dfce03b 140 char **envp = build_env (env ?: cur_environ (), envblock, unused_envc, false);
752b16ce 141 PWCHAR p = envblock;
6577c186 142
9a08fd5a 143 if (envp)
6577c186 144 {
9a08fd5a
CF
145 for (char **e = envp; *e; e++)
146 cfree (*e);
147 cfree (envp);
6577c186 148 }
8dfce03b
CV
149 /* If we got an env block, just return pointer to win env. */
150 if (env)
151 return envblock;
152 /* Otherwise sync win env of current process with its posix env. */
9a08fd5a 153 if (!p)
8dfce03b 154 return NULL;
9a08fd5a
CF
155 while (*p)
156 {
752b16ce 157 PWCHAR eq = wcschr (p, L'=');
9a08fd5a
CF
158 if (eq)
159 {
752b16ce
CV
160 *eq = L'\0';
161 SetEnvironmentVariableW (p, ++eq);
9a08fd5a
CF
162 p = eq;
163 }
752b16ce 164 p = wcschr (p, L'\0') + 1;
9a08fd5a
CF
165 }
166 free (envblock);
8dfce03b 167 return NULL;
6577c186
CF
168}
169
c8ee587a
CW
170/*
171 * Cygwin-specific wrapper for win32 ExitProcess and TerminateProcess.
172 * It ensures that the correct exit code, derived from the specified
173 * status value, will be made available to this process's parent (if
174 * that parent is also a cygwin process). If useTerminateProcess is
175 * true, then TerminateProcess(GetCurrentProcess(),...) will be used;
176 * otherwise, ExitProcess(...) is called.
177 *
178 * Used by startup code for cygwin processes which is linked statically
179 * into applications, and is not part of the cygwin DLL -- which is why
180 * this interface is exposed. "Normal" programs should use ANSI exit(),
181 * ANSI abort(), or POSIX _exit(), rather than this function -- because
182 * calling ExitProcess or TerminateProcess, even through this wrapper,
183 * skips much of the cygwin process cleanup code.
184 */
185static void
186exit_process (UINT status, bool useTerminateProcess)
187{
188 pid_t pid = getpid ();
fb348d22 189 external_pinfo *ep = fillout_pinfo (pid, 1);
c8ee587a
CW
190 DWORD dwpid = ep ? ep->dwProcessId : pid;
191 pinfo p (pid, PID_MAP_RW);
fb348d22
CF
192 if (ep)
193 pid = ep->pid;
194 if ((dwpid == GetCurrentProcessId()) && (p->pid == pid))
c8ee587a
CW
195 p.set_exit_code ((DWORD)status);
196 if (useTerminateProcess)
197 TerminateProcess (GetCurrentProcess(), status);
198 /* avoid 'else' clause to silence warning */
199 ExitProcess (status);
200}
201
202
61522196 203extern "C" uintptr_t
1fd5e000
CF
204cygwin_internal (cygwin_getinfo_types t, ...)
205{
206 va_list arg;
6259826e 207 uintptr_t res = (uintptr_t) -1;
1fd5e000
CF
208 va_start (arg, t);
209
210 switch (t)
211 {
212 case CW_LOCK_PINFO:
4cd31fc8
EB
213 res = 1;
214 break;
1fd5e000
CF
215
216 case CW_UNLOCK_PINFO:
4cd31fc8
EB
217 res = 1;
218 break;
1fd5e000
CF
219
220 case CW_GETTHREADNAME:
61522196 221 res = (uintptr_t) cygthread::name (va_arg (arg, DWORD));
4cd31fc8 222 break;
1fd5e000
CF
223
224 case CW_SETTHREADNAME:
225 {
b6bd7037 226 set_errno (ENOSYS);
4cd31fc8 227 res = 0;
1fd5e000 228 }
4cd31fc8 229 break;
1fd5e000
CF
230
231 case CW_GETPINFO:
61522196 232 res = (uintptr_t) fillout_pinfo (va_arg (arg, DWORD), 0);
4cd31fc8 233 break;
1fd5e000
CF
234
235 case CW_GETVERSIONINFO:
61522196 236 res = (uintptr_t) cygwin_version_strings;
4cd31fc8 237 break;
1fd5e000
CF
238
239 case CW_READ_V1_MOUNT_TABLES:
50484e8e 240 set_errno (ENOSYS);
4cd31fc8
EB
241 res = 1;
242 break;
1fd5e000 243
85219b35 244 case CW_USER_DATA:
adfbdcdb
CF
245 /* This is a kludge to work around a version of _cygwin_common_crt0
246 which overwrote the cxx_malloc field with the local DLL copy.
247 Hilarity ensues if the DLL is not loaded like while the process
248 is forking. */
249 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
61522196 250 res = (uintptr_t) &__cygwin_user_data;
4cd31fc8 251 break;
85219b35 252
bd4ec496
CF
253 case CW_PERFILE:
254 perfile_table = va_arg (arg, struct __cygwin_perfile *);
4cd31fc8
EB
255 res = 0;
256 break;
bd4ec496 257
637f5ce0
CF
258 case CW_GET_CYGDRIVE_PREFIXES:
259 {
260 char *user = va_arg (arg, char *);
261 char *system = va_arg (arg, char *);
4cd31fc8 262 res = get_cygdrive_info (user, system, NULL, NULL);
637f5ce0 263 }
4cd31fc8 264 break;
637f5ce0 265
84c7d409 266 case CW_GETPINFO_FULL:
61522196 267 res = (uintptr_t) fillout_pinfo (va_arg (arg, pid_t), 1);
4cd31fc8 268 break;
84c7d409 269
239b06b8 270 case CW_INIT_EXCEPTIONS:
f153e6b2 271 /* noop */ /* init_exceptions (va_arg (arg, exception_list *)); */
4cd31fc8
EB
272 res = 0;
273 break;
239b06b8 274
9bc846bd
CF
275 case CW_GET_CYGDRIVE_INFO:
276 {
277 char *user = va_arg (arg, char *);
278 char *system = va_arg (arg, char *);
279 char *user_flags = va_arg (arg, char *);
280 char *system_flags = va_arg (arg, char *);
4cd31fc8 281 res = get_cygdrive_info (user, system, user_flags, system_flags);
9bc846bd 282 }
4cd31fc8 283 break;
9bc846bd 284
a9f20457 285 case CW_SET_CYGWIN_REGISTRY_NAME:
a9f20457 286 case CW_GET_CYGWIN_REGISTRY_NAME:
4cd31fc8
EB
287 res = 0;
288 break;
a9f20457 289
907dc7d0 290 case CW_STRACE_TOGGLE:
494a66d9
CF
291 {
292 pid_t pid = va_arg (arg, pid_t);
293 pinfo p (pid);
294 if (p)
295 {
296 sig_send (p, __SIGSTRACE);
4cd31fc8 297 res = 0;
494a66d9
CF
298 }
299 else
300 {
301 set_errno (ESRCH);
61522196 302 res = (uintptr_t) -1;
494a66d9
CF
303 }
304 }
4cd31fc8 305 break;
907dc7d0 306
3d456520
CF
307 case CW_STRACE_ACTIVE:
308 {
4cd31fc8 309 res = strace.active ();
3d456520 310 }
4cd31fc8 311 break;
3d456520 312
494a66d9
CF
313 case CW_CYGWIN_PID_TO_WINPID:
314 {
315 pinfo p (va_arg (arg, pid_t));
4cd31fc8 316 res = p ? p->dwProcessId : 0;
494a66d9 317 }
4cd31fc8 318 break;
31b98a62 319 case CW_EXTRACT_DOMAIN_AND_USER:
7c02f861 320 {
b5488135
CV
321 WCHAR nt_domain[MAX_DOMAIN_NAME_LEN + 1];
322 WCHAR nt_user[UNLEN + 1];
323
31b98a62
CV
324 struct passwd *pw = va_arg (arg, struct passwd *);
325 char *domain = va_arg (arg, char *);
326 char *user = va_arg (arg, char *);
b5488135
CV
327 extract_nt_dom_user (pw, nt_domain, nt_user);
328 if (domain)
329 sys_wcstombs (domain, MAX_DOMAIN_NAME_LEN + 1, nt_domain);
330 if (user)
331 sys_wcstombs (user, UNLEN + 1, nt_user);
4cd31fc8 332 res = 0;
31b98a62 333 }
4cd31fc8 334 break;
831d6fa5
CF
335 case CW_CMDLINE:
336 {
1114c3d0 337 size_t n;
831d6fa5
CF
338 pid_t pid = va_arg (arg, pid_t);
339 pinfo p (pid);
61522196 340 res = (uintptr_t) p->cmdline (n);
831d6fa5 341 }
4cd31fc8 342 break;
5a4a19b3
CV
343 case CW_CHECK_NTSEC:
344 {
345 char *filename = va_arg (arg, char *);
4cd31fc8 346 res = check_ntsec (filename);
5a4a19b3 347 }
4cd31fc8 348 break;
5ec9ea21 349 case CW_GET_ERRNO_FROM_WINERROR:
e3778517 350 {
5ec9ea21
CV
351 int error = va_arg (arg, int);
352 int deferrno = va_arg (arg, int);
4cd31fc8 353 res = geterrno_from_win_error (error, deferrno);
5ec9ea21 354 }
4cd31fc8 355 break;
bcd06214
CV
356 case CW_GET_POSIX_SECURITY_ATTRIBUTE:
357 {
88797e59 358 path_conv dummy;
12069cf3 359 security_descriptor sd;
bcd06214
CV
360 int attribute = va_arg (arg, int);
361 PSECURITY_ATTRIBUTES psa = va_arg (arg, PSECURITY_ATTRIBUTES);
362 void *sd_buf = va_arg (arg, void *);
363 DWORD sd_buf_size = va_arg (arg, DWORD);
88797e59 364 set_security_attribute (dummy, attribute, psa, sd);
2be593d9 365 if (!psa->lpSecurityDescriptor)
4cd31fc8
EB
366 res = sd.size ();
367 else
368 {
369 psa->lpSecurityDescriptor = sd_buf;
370 res = sd.copy (sd_buf, sd_buf_size);
371 }
e3778517 372 }
4cd31fc8 373 break;
6ef3b76b 374 case CW_GET_SHMLBA:
e3778517 375 {
177dc6c7 376 res = wincap.allocation_granularity ();
6ef3b76b 377 }
4cd31fc8 378 break;
8e68687d 379 case CW_GET_UID_FROM_SID:
e3778517 380 {
0740b418 381 cygpsid psid = va_arg (arg, PSID);
4cd31fc8 382 res = psid.get_id (false, NULL);
8e68687d 383 }
4cd31fc8 384 break;
8e68687d 385 case CW_GET_GID_FROM_SID:
e3778517 386 {
0740b418 387 cygpsid psid = va_arg (arg, PSID);
4cd31fc8 388 res = psid.get_id (true, NULL);
8e68687d 389 }
4cd31fc8 390 break;
5ef9bbc8
CF
391 case CW_GET_BINMODE:
392 {
393 const char *path = va_arg (arg, const char *);
063f1df2 394 path_conv p (path, PC_SYM_FOLLOW | PC_NULLEMPTY);
5ef9bbc8
CF
395 if (p.error)
396 {
397 set_errno (p.error);
4cd31fc8 398 res = (unsigned long) -1;
5ef9bbc8 399 }
4cd31fc8
EB
400 else
401 res = p.binmode ();
5ef9bbc8 402 }
4cd31fc8 403 break;
b1d9a0bd
CF
404 case CW_HOOK:
405 {
406 const char *name = va_arg (arg, const char *);
407 const void *hookfn = va_arg (arg, const void *);
247ac234 408 WORD subsys;
61522196 409 res = (uintptr_t) hook_or_detect_cygwin (name, hookfn, subsys);
b1d9a0bd 410 }
4cd31fc8 411 break;
1cd8ccec
CF
412 case CW_ARGV:
413 {
414 child_info_spawn *ci = (child_info_spawn *) get_cygwin_startup_info ();
61522196 415 res = (uintptr_t) (ci ? ci->moreinfo->argv : NULL);
1cd8ccec 416 }
4cd31fc8 417 break;
1cd8ccec
CF
418 case CW_ENVP:
419 {
420 child_info_spawn *ci = (child_info_spawn *) get_cygwin_startup_info ();
61522196 421 res = (uintptr_t) (ci ? ci->moreinfo->envp : NULL);
1cd8ccec 422 }
4cd31fc8 423 break;
5c8e6fbd
CF
424 case CW_DEBUG_SELF:
425 error_start_init (va_arg (arg, const char *));
61522196 426 res = try_to_debug ();
5c8e6fbd 427 break;
9a08fd5a 428 case CW_SYNC_WINENV:
8dfce03b 429 create_winenv (NULL);
4cd31fc8
EB
430 res = 0;
431 break;
38229bcd 432 case CW_CYGTLS_PADSIZE:
4cd31fc8
EB
433 res = CYGTLS_PADSIZE;
434 break;
e7fd6e57
CF
435 case CW_SET_DOS_FILE_WARNING:
436 {
e7fd6e57 437 dos_file_warning = va_arg (arg, int);
4cd31fc8 438 res = 0;
e7fd6e57
CF
439 }
440 break;
51303cbd
CV
441 case CW_SET_PRIV_KEY:
442 {
443 const char *passwd = va_arg (arg, const char *);
1db2e3fb
CV
444 const char *username = va_arg (arg, const char *);
445 res = setlsapwd (passwd, username);
51303cbd 446 }
4cd31fc8 447 break;
d95d8c53
CF
448 case CW_SETERRNO:
449 {
450 const char *file = va_arg (arg, const char *);
451 int line = va_arg (arg, int);
452 seterrno(file, line);
4cd31fc8 453 res = 0;
d95d8c53
CF
454 }
455 break;
c8ee587a
CW
456 case CW_EXIT_PROCESS:
457 {
458 UINT status = va_arg (arg, UINT);
459 int useTerminateProcess = va_arg (arg, int);
460 exit_process (status, !!useTerminateProcess); /* no return */
461 }
0191627a
CV
462 case CW_SET_EXTERNAL_TOKEN:
463 {
464 HANDLE token = va_arg (arg, HANDLE);
465 int type = va_arg (arg, int);
466 set_imp_token (token, type);
4cd31fc8 467 res = 0;
0191627a 468 }
4cd31fc8 469 break;
526b0fbc
CV
470 case CW_GET_INSTKEY:
471 {
526b0fbc 472 PWCHAR dest = va_arg (arg, PWCHAR);
8895d962 473 wcscpy (dest, cygheap->installation_key_buf);
526b0fbc
CV
474 res = 0;
475 }
476 break;
f5a73638
CV
477 case CW_INT_SETLOCALE:
478 {
479 extern void internal_setlocale ();
480 internal_setlocale ();
481 res = 0;
482 }
a11a0723
CV
483 break;
484 case CW_CVT_MNT_OPTS:
485 {
486 extern bool fstab_read_flags (char **, unsigned &, bool);
487 char **option_string = va_arg (arg, char **);
488 if (!option_string || !*option_string)
489 set_errno (EINVAL);
490 else
491 {
492 unsigned *pflags = va_arg (arg, unsigned *);
8ae578d6 493 unsigned flags = pflags ? *pflags : 0;
a11a0723
CV
494 if (fstab_read_flags (option_string, flags, true))
495 {
496 if (pflags)
497 *pflags = flags;
498 res = 0;
499 }
500 }
501 }
502 break;
503 case CW_LST_MNT_OPTS:
504 {
505 extern char *fstab_list_flags ();
506 char **option_string = va_arg (arg, char **);
507 if (!option_string)
508 set_errno (EINVAL);
509 else
510 {
511 *option_string = fstab_list_flags ();
512 if (*option_string)
513 res = 0;
514 }
515 }
516 break;
6259826e
CF
517 case CW_STRERROR:
518 {
519 int err = va_arg (arg, int);
520 res = (uintptr_t) strerror (err);
521 }
522 break;
e7fd6e57 523
8dfce03b
CV
524 case CW_CVT_ENV_TO_WINENV:
525 {
526 char **posix_env = va_arg (arg, char **);
527 res = (uintptr_t) create_winenv (posix_env);
528 }
529 break;
530
3a24189b
CV
531 case CW_ALLOC_DRIVE_MAP:
532 {
533 dos_drive_mappings *ddm = new dos_drive_mappings ();
534 res = (uintptr_t) ddm;
535 }
536 break;
537
538 case CW_MAP_DRIVE_MAP:
539 {
540 dos_drive_mappings *ddm = va_arg (arg, dos_drive_mappings *);
541 wchar_t *pathbuf = va_arg (arg, wchar_t *);
542 if (ddm && pathbuf)
543 res = (uintptr_t) ddm->fixup_if_match (pathbuf);
544 }
545 break;
546
547 case CW_FREE_DRIVE_MAP:
548 {
549 dos_drive_mappings *ddm = va_arg (arg, dos_drive_mappings *);
550 if (ddm)
551 delete ddm;
552 res = 0;
553 }
554 break;
555
1fd5e000 556 default:
4cd31fc8 557 set_errno (ENOSYS);
1fd5e000 558 }
4cd31fc8
EB
559 va_end (arg);
560 return res;
1fd5e000 561}
This page took 0.46957 seconds and 5 git commands to generate.