aboutsummaryrefslogtreecommitdiff
path: root/win32/process.c (follow)
Commit message (Collapse)AuthorAgeFilesLines
* win32: retry when command needs elevated privilegesRon Yorston2025-02-031-0/+42
| | | | | | | | | | | | | | Some installer programs have an entry in their manifest to indicate that they need elevated privileges. The shell in busybox-w32 was unable to run such programs. When a program fails to run with ERROR_ELEVATION_REQUIRED, try again using ShellExecuteEx() with the 'runas' verb to give it elevated privileges. Adds 272-288 bytes. (GitHub issue #481)
* win32: fix compilation with FEATURE_SH_NOFORK disabledRon Yorston2024-12-311-0/+2
| | | | | Compiling with FEATURE_SH_NOFORK disabled resulted in an error and a warning. Fixing these doesn't change the default build.
* win32: code shrink quote_arg()Ron Yorston2024-12-301-24/+20
| | | | | | | | Alter quote_arg() to perform a single pass over the string in the case where no change is required. Based on a proposal by @avih in GitHub PR #317. Saves 16 bytes.
* win32: close exec'ing process if possibleRon Yorston2024-10-131-0/+3
| | | | | | | | | If a process performing an exec is an orphan there's no reason for it to wait for its child's exit code. Let it exit immediately. Adds 16 bytes. (GitHub issue #461)
* kill: fix regression in 'kill -9'Ron Yorston2024-10-121-6/+7
| | | | | | | | | | | | | | 'kill -9' was found to fail with an 'Invalid argument' error. This is a regression introduced by commit 569de936a (kill: killing a zombie process should fail). Use the correct argument to OpenProcess() for SIGKILL so it can query the exit code of the target process. Adds 16 bytes. (GitHub issue #465)
* win32: fix problem interrupting shell loopRon Yorston2024-10-111-11/+13
| | | | | | | | | | | | | | | | | It proved to be almost impossible to interrupt a loop like: while true; do sleep 1; done where 'sleep' was an external program, not an applet. The issue was introduced by commit 0475b7a64 (win32: convert exit codes). This passed a POSIX error code to the exit() in wait_for_child() so a parent was unable to detect when its child was interrupted. Pass the Windows exit code to exit() instead. Work around the changes introduced by commit 790e377273 (win32: revert 'don't set error mode'). Adds 16-32 bytes.
* Merge branch 'busybox' into mergeRon Yorston2024-10-081-1/+1
|
* ash: optimise running of scriptsRon Yorston2024-08-191-8/+1
| | | | | | | | | | | | | | | | | | | | | | The BusyBox shell detects certain cases where forking a command is unnecessary (last command in a script or subshell, for example) and calls execve(2) instead. This doesn't help in the Windows port because execve(2) is implemented by creating a process. There is one case where it is possible to apply this optimisation: if the command is a script and the script interpreter is an applet. - Have evalcommand() pass a flag to indicate this situation to shellexec(). Also, allocate two spare elements before the start of the argv array. - If the flag is TRUE shellexec() passes the shell's PATH variable down to tryexec() so it can perform a test for applet override. - If tryexec() finds that all the necessary conditions apply it can run a script by directly invoking the interpreter's main(). Adds 192-224 bytes.
* win32: code shrinkRon Yorston2024-08-161-2/+2
| | | | | Add the FAST_FUNC qualifier to several Windows-specific functions. This has no effect in 64-bit builds but saves 336 bytes for 32-bit.
* win32: code shrink mingw_spawn_interpreter()Ron Yorston2024-07-141-11/+8
| | | | | | | Rewrite mingw_spawn_interpreter() to remove a duplicated recursive call. Saves 32-48 bytes.
* win32: code shrink exit_code_to_wait_status_cmd()Ron Yorston2024-06-241-4/+4
| | | | Saves 16 bytes.
* win32: revert 'don't set error mode'Ron Yorston2024-06-221-29/+64
| | | | | | | | | | | | | | | | | | | | | | | | Commit eb376b5d1 (win32: don't set error mode) removed a call to SetErrorMode(SEM_FAILCRITICALERRORS). But the documentation says: Best practice is that all applications call the process-wide SetErrorMode function with a parameter of SEM_FAILCRITICALERRORS at startup. This is to prevent error mode dialogs from hanging the application. Doing this prevents the system from displaying useful information, though. The application should attempt to tell the user what went wrong. Reinstate the call to SetErrorMode() and try to provide an error message, at least for the situation mentioned in issue #423 and other similar cases. Adds 360-368 bytes. (GitHub issue #423)
* win32: some changes to kill(2)Ron Yorston2024-05-181-26/+27
| | | | | | | | Merge the kill() and kill_pids() functions. Allocate an array for the PIDs rather than use a hardcoded one. Adds 32 bytes to the 32-bit build, none to 64-bit.
* win32: implement getppid(2)Ron Yorston2024-05-161-9/+24
| | | | | | | | | | | | | | busybox-w32 had a dummy implementation of getppid(2) which always returned 1. Provide a more realistic version. The effect is limited: - The PPID shell variable should report a sensible value. - The special value to omit the parent PID 'pidof -o %PPID' should work. Costs 48 bytes.
* win32: ensure PIDs are read early in procps_scan()Ron Yorston2024-05-161-10/+15
| | | | | | | | | | | Recent changes to allow orphaned processes to report a parent PID of 1 rely on the assumption that Process32First/Process32Next return parents before children. This isn't guaranteed by the API. Obtain all known PIDs on the first call to procps_scan() so that dead parents can be detected reliably. Costs 48 bytes.
* win32: code shrinkRon Yorston2024-05-151-2/+0
| | | | Saves 16-32 bytes
* ps: report unknown parent PID as 1Ron Yorston2024-05-141-2/+20
| | | | | | | | | | If the parent PID doesn't appear in the process table, report it as 1. This more closely matches how orphaned children are handled on UNIX. Adds 96-128 bytes. (GitHub issue #416)
* kill: killing a zombie process should failRon Yorston2024-05-141-106/+90
| | | | | | | | | | | | | | | | | | | | | | | A process which has exited may still have its process handle held open by its children. Such a process doesn't appear in the process table. It is thus similar to a zombie process in UNIX. Using kill(1) to interact with such a process was seen to succeed, contrary to expectation. The code for "ordinary" signals in kill(2) did check if the process was still active but didn't treat an attempt to kill an inactive process as an error. Furthermore, sending SIGKILL or the fake signal 0 to a process didn't even check if the process was still active. Rearrange the implementation of kill(2) so that an attempt to signal an inactive process is treated as an error. This also consolidates handling of SIGKILL and signal 0 with "ordinary" signals. Saves 96 bytes. (GitHub issue #416)
* win32: avoid console windows from CGI scriptsRon Yorston2024-02-071-1/+1
| | | | | | | | | When httpd is run in the background its processes are detached from the console. CGI scripts could create subprocesses which needed a console, resulting in annoying console windows appearing. Prevent this by changing the creation flags for CGI scripts to CREATE_NO_WINDOW.
* win32: code shrink procps_scan()Ron Yorston2023-12-311-2/+2
| | | | | | Use getpid() instead of GetProcessId(GetCurrentProcess()). Saves 16 bytes.
* httpd: consistently leak memory, or notRon Yorston2023-12-311-3/+8
| | | | | | | | | | | | | create_detached_process() is only used when running a CGI script. Previously it leaked the return values from quote_arg() but freed the command line it built. Whether or not the CGI script is successfully run its parent process exits almost immediately, so there's no pressing need to free the memory. If FEATURE_CLEAN_UP is disabled (which it is by default) don't bother. Saves 16 bytes.
* httpd: enable support for CGIRon Yorston2023-12-201-2/+58
| | | | | | | | | | | | | | | | | | | | | | | | | The upstream code uses fork/exec when running a CGI process. Emulate this by: - Spawning a child httpd process with the special '-I 0' option, along with the options provided on the server command line. This sets up the proper state then calls the cgi_handler() function. - The cgi_handler() function fixes the pipe file descriptors and starts another child process to run the CGI script. These processes are detached from the console on creation. When spawn() functions are run in P_DETACH mode they don't connect to the standard file descriptors. Normally this doesn't matter but the process which runs the CGI scripts needs to inherit the pipe endpoints. The create_detached_process() function handles this. See: https://github.com/rprichard/win32-console-docs/blob/master/README.md Adds about 2.9Kb to the size of the binary. (GitHub issue #266)
* win32: code shrink execve(2) implementationRon Yorston2023-12-181-2/+2
| | | | | | | | | | | Commit 6d6856355a (win32: handle -1 return status from execve(2)) added a test of errno to distinguish between failure to run a program and the program returning -1. Subsequent changes in commit 9db9b34ada (win32: ignore ctrl-c in parent of execve(2)) make this test unnecessary. Remove it. Saves 16-32 bytes.
* httpd: fix return code when run in backgroundRon Yorston2023-12-151-11/+5
| | | | | | | | | | | When httpd was run in the background the return code of the parent process was incorrect. It seems when spawn() is run in _P_DETACH mode it returns 0 on success, not a process handle. Fix the test for the return code and alter mingw_spawn_detach() so it doesn't treat the return from spawn() as a handle. Saves 32 bytes.
* win32: convert exit codesRon Yorston2023-09-141-2/+35
| | | | | | | | | | | | | | | | | Add two utility functions to convert Windows process exit codes. - exit_code_to_wait_status() converts to a POSIX wait status. This is used in ash and the implementations of system(3) and mingw_wait3(). - exit_code_to_posix() converts to a POSIX exit code. (Not that POSIX has much to say about them.) As a result it's possible for more applets to report when child processes are killed as if by a signal. 'time', 'drop' and 'su -W', for example. Adds 64-80 bytes.
* win32: change interpretation of BB_OVERRIDE_APPLETSRon Yorston2023-06-021-10/+2
| | | | | | | | | | | | | | | | | | | | | | | | | Make the following changes to BB_OVERRIDE_APPLETS: - Applet names in the list can be separated by spaces, commas or semicolons. - Applets before the first semicolon are disabled unconditionally. - Applets after the first semicolon are overridden if a matching external command exists. - '-' alone disables all applets. - '+' alone overrides every applet for which a matching external command exists. This doesn't change the existing documented behaviour. It adds the ability to have applets overridden if an external command exists but to remain available if not. Adds 80-88 bytes. (GitHub issue #329)
* win32: skip test for non-console apps if necessaryRon Yorston2023-06-021-0/+4
| | | | | | | | | Commit 20b6a57af (win32: crtl-c interrupts non-console applications) introduced a test for non-console apps in the Ctrl-C handler. Skip this if GetConsoleProcessList() isn't available. Costs 68-88 bytes.
* win32: crtl-c interrupts non-console applicationsRon Yorston2023-05-231-1/+36
| | | | | | | | | | | | | | | | | | | Commit 9db9b34ad (win32: ignore ctrl-c in parent of execve(2)) prevented a parent process from reacting to Ctrl-C while it was waiting for its child to complete. This avoids the problem where a shell and an interactive child end up competing for input after a Ctrl-C. However, a child process which isn't attached to the console (a GUI application, for example) can't then be killed by Ctrl-C. Instead of completely ignoring Ctrl-C give the parent a handler which detects if its child is attached to the console. If so it's left to handle Ctrl-C itself and the parent ignores the interrupt. If not the parent terminates the child and all its children as if by SIGINT. Costs 200 bytes.
* win32: changes to signal handlingRon Yorston2023-05-231-8/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | Use an exit code of the form (signal << 24) when a process exits due to a signal. This replaces the previous use of (signal + 128). This makes it easier to distinguish exit codes from signals. Allow kill(2) to handle all defined signals, not just EXIT, TERM and KILL. The kill and timeout applets now accept any defined signals. Convert certain Windows status codes Unix-style signal codes. In ash: - Exit as if with SIGINT in raise_interrupt() rather than call raise(SIGINT). The latter returns an exit code of 3. - Detect if a child process exits as if with SIGINT. If not and if the parent is an interactive top-level shell, reset pending_int. This prevents the parent from seeing an INT if the child hasn't reported it exited due to INT. (Probably due to it being an interactive shell.) Costs 132-136 bytes.
* win32: further code shrink quote_args()Ron Yorston2023-04-281-19/+3
| | | | | | | | Squeeze a few more bytes out of quote_args(). (Thanks to GitHub user avih.) Saves 16 bytes.
* win32: code shrink copying of argvRon Yorston2023-04-281-4/+14
| | | | | | | There are two places where a copy of an argv array is made with extra space at the start. Move this code into a function. Saves 56-64 bytes.
* win32: improved error for overlong command lineRon Yorston2023-04-271-1/+6
| | | | | | | | Report 'Arg list too long' rather than 'Invalid argument' when spawnveq() detects that the EINVAL return from spawnve() is due to the command line being too long. Costs 48-64 bytes.
* win32: code shrink quote_args()Ron Yorston2023-04-271-58/+20
| | | | | | | | | | | | | | | Replace parts of quote_args() with code from avih's GitHub PR #317. This overestimates the size of the buffer to avoid having to calculate the exact size. Retain the code to determine whether the argument needs to be quoted. Quoting arguments unconditionally wastes space on the command line and causes the test "xargs argument line too long" to fail. Saves 144-176 bytes.
* win32: further fix incorrect path search in spawnvpRon Yorston2023-04-161-1/+3
| | | | | | | | Commit 9581d2396 (win32: fix incorrect path search in spawnvp) fixed the unwanted PATH search for relative or absolute paths but broke the desired PATH search for Unix-style paths. (GitHub issue #310)
* win32: fix incorrect path search in spawnvpRon Yorston2023-04-141-3/+1
| | | | | | | | | Commit 26ba73098e (win32: search PATH for missing Unix-style executables) rearranged the code of mingw_spawnvp(). As a result commands with a relative or absolute path could be incorrectly searched for on PATH. (GitHub issue #310)
* win32: ignore ctrl-c in parent of execve(2)Ron Yorston2023-04-051-4/+14
| | | | | | | | | | | | | | | | | | The execve(2) system call is emulated for Microsoft Windows. This requires the creation of a new process. The old process remains active, waiting for the "execed" child to exit so it can pass on its exit status. Previously this was achieved using P_WAIT mode in the call to spawnve(). However the parent of the execve(2) process may still be able to catch Ctrl-C interrupts. This can lead to unwanted behaviour, such as a shell and its children competing for input. Force the waiting process to ignore Ctrl-C interrupts. Costs 64-80 bytes. (GitHub issue #303)
* runuser,drop: code shrinkRon Yorston2023-03-191-3/+2
| | | | | | | | | Make quote_arg() always return an allocated string so we can free it unconditionally. Always use argv[1] as the first part of the command string. Saves 48 bytes.
* runuser: add 'drop' as an alias for runuserRon Yorston2023-03-161-1/+1
| | | | | | | | | | | | | | | | | | | The 'drop' alias for 'runuser' relaxes a number of constraints that were introduced for compatibility: - It works even if the current process doesn't have elevated privileges. - It isn't necessary to specify the name of the user. - Any command can be invoked, not just the BusyBox shell. - If the command doesn't specify a path 'drop' will first look for a BusyBox applet then search PATH. Adds 320-336 when built along with runuser. (GitHub issue #240)
* win32: code shrink detection of executablesRon Yorston2023-03-161-7/+4
| | | | | | | | | | | | Add a function, file_is_win32_exe(), to detect if a path refers to an executable. It tries adding extensions if necessary. Use this in a number of places to replace common code of the form path = alloc_ext_space(cmd); if (add_win32_extension(path) || file_is_executable(path)) Saves 32-48 bytes.
* runuser: new appletRon Yorston2023-03-131-1/+1
| | | | | | | | | | | | | | | | | | | | | Add a cut down, Windows-specific implementation of `runuser` from util-linux. This allows elevated privileges to be dropped when running in an SSH session. It also works when using `su` or starting busybox-w32 'as administrator'. There are complications: - The method used to drop privileges leaves the access token in the TokenIsElevated state. Detecting this is likely to be fragile. - The unprivileged shell is started by CreateProcessAsUserA(). In older versions of Windows this has to be loaded dynamically. Adds about 900 bytes. (GitHub issue #240)
* win32: revert special treatment of Unix-style absolute pathsRon Yorston2022-10-261-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | Commit 605972390 (win32: handle Unix-style absolute paths for executables) added special treatment of paths for executables starting with a slash. Such paths are absolute on Unix but are relative to the current drive on Windows. On reflection this commit did more than necessary. Later commits provided special treatment only for paths starting with locations traditionally used to contain binaries on Unix. This is probably sufficient. Problems introduced by commit 605972390 include: - If the current drive isn't the system drive tab completion of a command starting with a slash confusingly references the system drive. - Building busybox-w32 with w64devkit fails on drives other than the system drive. Revert the changes introduced by commit 605972390. This saves 192 bytes. (GitHub issue #239)
* win32: search PATH for missing Unix-style executablesRon Yorston2022-05-061-29/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Commit 41ef232fc5 (win32: use built-in applets for non-existent binaries with Unix-style paths) alters what happens when trying to find an executable. If all of the following apply: - the pathname starts with one of the standard directories for Unix executables (/bin, /usr/bin, /sbin, /usr/sbin); - the file isn't found relative to the system root; - the basename matches an applet then the applet is run. Further extend the procedure so that if the first two conditions are met and either: - the PREFER_APPLETS and SH_STANDALONE features are enabled and the basename *doesn't* match an applet or - the PREFER_APPLETS and SH_STANDALONE features are disabled then PATH is searched for the basename. This affects: - how interpreters and binaries are spawned by mingw_spawn_interpreter() and mingw_spawnvp(); - how 'which' and the shell search for binaries. Special steps need to be taken in the shell to avoid treating shell built-ins and functions as applets. As a consequence of this change: - An executable that isn't an applet, say curl.exe, can be run as /usr/bin/curl so long as it's in a directory in PATH. It doesn't have to be in C:/usr/bin. - If the PREFER_APPLETS and SH_STANDALONE features are disabled binaries can be run using paths referring to standard Unix directories even if they're installed elsewhere in PATH.
* win32: better fix for empty environment variablesRon Yorston2022-05-051-9/+4
| | | | | | | | | | | | | | | | | | | It appears the CRT and OS each have a copy of the environment. mingw_putenv() fools the CRT into accepting an empty environment variable by calling _putenv("V=0") then truncating the new value by hand. But _putenv() also updates the OS environment with the fake 'V=0' value. Commit 5b48ca53b (win32: pass NULL to spawnve, not environ) resulted in this fake value being used and hence empty variables getting the value '0'. - Add a call to SetEnvironmentVariable() in mingw_putenv() to update the OS environment. - Restore the use of NULL environment pointers in mingw_spawnvp(). - Add a test. (GitHub issue #250)
* win32: revert changes related to environment variablesRon Yorston2022-05-041-4/+9
| | | | | | | | | | Revert the change to mingw_putenv() in the previous commit. When compiling for MSVCRT (i.e. not for UCRT) revert some of the changes from commit 5b48ca53b (win32: pass NULL to spawnve, not environ). (GitHub issue #250)
* win32: conditional compilation in process.cRon Yorston2022-04-241-10/+10
| | | | | | | Drop the use of ENABLE_FEATURE_SH_STANDALONE in process.c In mingw_spawn_interpreter() check for an applet *before* trying to run the interpreter using the path provided.
* win32: add link to LWN article on shebangRon Yorston2021-11-141-1/+2
|
* win32: rename mingw_spawn_1Ron Yorston2021-11-011-8/+8
| | | | | | | | | | The name of the function mingw_spawn_1() wasn't particularly meaningful. Remove its envp argument (as all of its current callers pass a NULL pointer) and rename it mingw_spawnvp() to better reflect what it does. The path search it performs isn't the standard one: it has features specific to busybox-w32.
* win32: pass NULL to spawnve, not environRon Yorston2021-10-281-4/+4
| | | | | | | | | | | | Building busybox-w32 for use with UCRT results in mysterious failures. (GitHub issue #234) These are somehow related to the environment values passed to spawnve. In several places the global environ pointer was being passed to spawnve so the child would inherit its environment from the parent. This can also be achieved by passing a NULL pointer. This prevents the failures in at least some cases and also makes the binary smaller.
* win32: handle -1 return status from execve(2)Ron Yorston2021-06-191-2/+3
| | | | | | | | The implementations of execve(2) and execvp(3) were unable to distinguish between failure and a program returning a status of -1. Check the error return code to discriminate between these cases. See GitHub issue #218.
* ash: code shrinkRon Yorston2021-02-141-9/+0
| | | | | Since there's only one call to mingw_spawn_forkshell() we might as well just call spawnve() directly from ash.