Greatly expand system() shell code features

The cosmopolitan command interpreter now has 13 builtin commands,
variable support, support for ; / && / || syntax, asynchronous support,
and plenty of unit tests with bug fixes.

This change fixes a bug in posix_spawn() with null envp arg. strace
logging now uses atomic writes for scatter functions. Breaking change
renaming GetCpuCount() to _getcpucount(). TurfWar is now updated to use
the new token bucket algorithm. WIN32 affinity masks now inherit across
fork() and execve().
This commit is contained in:
Justine Tunney 2022-10-11 21:06:27 -07:00
parent e7329b7cba
commit b41f91c658
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
80 changed files with 1370 additions and 344 deletions

View file

@ -16,39 +16,51 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/nt/enum/processcreationflags.h"
#include "libc/paths.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/o.h"
/**
* Daemonizes process.
* Runs process in background.
*
* On Unix this calls fork() and setsid(). On Windows this is
* implemented using CreateProcess(kNtDetachedProcess).
*
* @return 0 on success, or -1 w/ errno
*/
int daemon(int nochdir, int noclose) {
int fd;
switch (fork()) {
switch (_fork(kNtDetachedProcess)) {
case -1:
return (-1);
return -1;
case 0:
break;
default:
_Exit(0);
}
if (setsid() == -1) {
return -1;
if (!IsWindows()) {
if (setsid() == -1) {
return -1;
}
}
if (!nochdir) {
chdir("/");
_unassert(!chdir("/"));
}
if (!noclose && (fd = open(_PATH_DEVNULL, O_RDWR)) != -1) {
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
_unassert(dup2(fd, 0) == 0);
_unassert(dup2(fd, 1) == 1);
_unassert(dup2(fd, 2) == 2);
if (fd > 2) {
close(fd);
_unassert(!close(fd));
}
}

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/ntspawn.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/calls/wincrash.internal.h"
#include "libc/errno.h"
@ -260,7 +261,7 @@ textwindows void WinMainForked(void) {
longjmp(jb, 1);
}
textwindows int sys_fork_nt(void) {
textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
bool ok;
jmp_buf jb;
uint32_t oldprot;
@ -302,7 +303,7 @@ textwindows int sys_fork_nt(void) {
}
#endif
if (ntspawn(GetProgramExecutableName(), args, environ, forkvar, 0, 0,
true, 0, 0, &startinfo, &procinfo) != -1) {
true, dwCreationFlags, 0, &startinfo, &procinfo) != -1) {
CloseHandle(procinfo.hThread);
ok = WriteAll(writer, jb, sizeof(jb)) &&
WriteAll(writer, &_mmi.i, sizeof(_mmi.i)) &&

View file

@ -21,6 +21,7 @@
#include "libc/calls/struct/sigset.internal.h"
#include "libc/calls/syscall-nt.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/process.h"
@ -28,15 +29,7 @@
#include "libc/sysv/consts/sig.h"
#include "libc/thread/tls.h"
/**
* Creates new process.
*
* @return 0 to child, child pid to parent, or -1 w/ errno
* @raise EAGAIN if `RLIMIT_NPROC` was exceeded or system lacked resources
* @raise ENOMEM if we require more vespene gas
* @asyncsignalsafe
*/
int fork(void) {
int _fork(uint32_t dwCreationFlags) {
axdx_t ad;
sigset_t old, all;
int ax, dx, parent;
@ -52,7 +45,7 @@ int fork(void) {
ax &= dx - 1;
}
} else {
ax = sys_fork_nt();
ax = sys_fork_nt(dwCreationFlags);
}
if (!ax) {
if (!IsWindows()) {
@ -73,3 +66,15 @@ int fork(void) {
}
return ax;
}
/**
* Creates new process.
*
* @return 0 to child, child pid to parent, or -1 w/ errno
* @raise EAGAIN if `RLIMIT_NPROC` was exceeded or system lacked resources
* @raise ENOMEM if we require more vespene gas
* @asyncsignalsafe
*/
int fork(void) {
return _fork(0);
}

View file

@ -103,6 +103,7 @@ void _intsort(int *, size_t);
void _longsort(long *, size_t);
bool _isheap(void *);
int NtGetVersion(void) pureconst;
unsigned _getcpucount(void) pureconst;
long _missingno();
void __oom_hook(size_t);
void _loadxmm(void *);

View file

@ -49,7 +49,7 @@ long sysconf(int name) {
case _SC_PAGESIZE:
return FRAMESIZE;
case _SC_NPROCESSORS_ONLN:
n = GetCpuCount();
n = _getcpucount();
return n > 0 ? n : -1;
default:
return -1;

View file

@ -147,7 +147,6 @@
COSMOPOLITAN_C_START_
long sysconf(int);
unsigned GetCpuCount(void);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -35,7 +35,7 @@
// @return pid of child process or 0 if forked process
// @returnstwice
// @vforksafe
vfork:
vfork: xor %edi,%edi # dwCreationFlags
#ifdef __SANITIZE_ADDRESS__
jmp fork # TODO: asan and vfork don't mix?
.endfn vfork,globl