]>
Commit | Line | Data |
---|---|---|
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 | ||
8 | This file is part of Cygwin. | |
9 | ||
10 | This software is a copyrighted work licensed under the terms of the | |
11 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
12 | details. */ | |
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 | 34 | child_info *get_cygwin_startup_info (); |
c8ee587a | 35 | static void exit_process (UINT, bool) __attribute__((noreturn)); |
b1d9a0bd | 36 | |
ac437c3e CF |
37 | static winpids pids; |
38 | ||
1fd5e000 | 39 | static external_pinfo * |
84c7d409 | 40 | fillout_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 | 116 | static inline uintptr_t |
9bc846bd | 117 | get_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 | 125 | static bool |
5a4a19b3 CV |
126 | check_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 |
135 | static PWCHAR |
136 | create_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 | */ | |
185 | static void | |
186 | exit_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 | 203 | extern "C" uintptr_t |
1fd5e000 CF |
204 | cygwin_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 | } |