Initial import
This commit is contained in:
41
libc/calls/hefty/access.c
Normal file
41
libc/calls/hefty/access.c
Normal file
@@ -0,0 +1,41 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
|
||||
/**
|
||||
* Checks if effective user can access path in particular ways.
|
||||
*
|
||||
* @param path is a filename or directory
|
||||
* @param mode can be R_OK, W_OK, X_OK, F_OK
|
||||
* @return 0 if ok, or -1 and sets errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int access(const char *path, int mode) {
|
||||
if (!IsWindows()) {
|
||||
return faccessat$sysv(AT_FDCWD, path, mode, 0);
|
||||
} else {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
return ntaccesscheck(path16, mode);
|
||||
}
|
||||
}
|
||||
170
libc/calls/hefty/commandv.c
Normal file
170
libc/calls/hefty/commandv.c
Normal file
@@ -0,0 +1,170 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/bits/progn.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/ntdll.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static struct critbit0 g_commandv;
|
||||
|
||||
textstartup static void g_commandv_init(void) {
|
||||
__cxa_atexit(critbit0_clear, &g_commandv, NULL);
|
||||
}
|
||||
|
||||
const void *const g_commandv_ctor[] initarray = {g_commandv_init};
|
||||
|
||||
static int accessexe(char pathname[hasatleast PATH_MAX], size_t len,
|
||||
const char *ext) {
|
||||
len = stpcpy(&pathname[len], ext) - &pathname[0];
|
||||
if (access(pathname, X_OK) != -1) {
|
||||
return len;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int accesscmd(char pathname[hasatleast PATH_MAX], const char *path,
|
||||
const char *name, size_t namelen) { /* cf. %PATHEXT% */
|
||||
int rc;
|
||||
char *p;
|
||||
bool hasdot;
|
||||
size_t pathlen, len;
|
||||
pathlen = strlen(path);
|
||||
if (pathlen + 1 + namelen + 1 + 4 + 1 > PATH_MAX) return -1;
|
||||
p = mempcpy(pathname, path, pathlen);
|
||||
if (pathlen) *p++ = '/';
|
||||
p = mempcpy(p, name, namelen);
|
||||
len = p - &pathname[0];
|
||||
hasdot = !!memchr(basename(name), '.', namelen);
|
||||
if ((hasdot && (rc = accessexe(pathname, len, "")) != -1) ||
|
||||
(!hasdot &&
|
||||
((rc = accessexe(pathname, len, ".com")) != -1 ||
|
||||
(IsWindows() && (rc = accessexe(pathname, len, ".exe")) != -1) ||
|
||||
(!IsWindows() && (rc = accessexe(pathname, len, "")) != -1)))) {
|
||||
return rc;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static int searchcmdpath(char pathname[hasatleast PATH_MAX], const char *name,
|
||||
size_t namelen) {
|
||||
int rc;
|
||||
char *ep, *path, *pathtok;
|
||||
struct critbit0 deduplicate;
|
||||
rc = -1;
|
||||
pathtok = ep =
|
||||
strdup(firstnonnull(getenv("PATH"), "/bin:/usr/local/bin:/usr/bin"));
|
||||
memset(&deduplicate, 0, sizeof(deduplicate));
|
||||
while ((path = strsep(&pathtok, IsWindows() ? ";" : ":"))) {
|
||||
if (strchr(path, '=')) continue;
|
||||
if (!critbit0_insert(&deduplicate, path)) continue;
|
||||
if ((rc = accesscmd(pathname, path, name, namelen)) != -1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
critbit0_clear(&deduplicate);
|
||||
free(ep);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static char *mkcmdquery(const char *name, size_t namelen,
|
||||
char scratch[hasatleast PATH_MAX]) {
|
||||
char *p;
|
||||
if (namelen + 1 + 1 > PATH_MAX) return NULL;
|
||||
p = mempcpy(scratch, name, namelen);
|
||||
*p++ = '=';
|
||||
*p++ = '\0';
|
||||
if (IsWindows() || IsXnu()) strntolower(scratch, namelen);
|
||||
return &scratch[0];
|
||||
}
|
||||
|
||||
static const char *cachecmd(const char *name, size_t namelen,
|
||||
const char *pathname, size_t pathnamelen) {
|
||||
size_t entrylen;
|
||||
char *res, *entry;
|
||||
if ((entry = malloc((entrylen = namelen + 1 + pathnamelen) + 1))) {
|
||||
mkcmdquery(name, namelen, entry);
|
||||
res = memcpy(&entry[namelen + 1], pathname, pathnamelen + 1);
|
||||
critbit0_emplace(&g_commandv, entry, entrylen);
|
||||
} else {
|
||||
res = NULL;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static const char *getcmdcache(const char *name, size_t namelen,
|
||||
char scratch[hasatleast PATH_MAX]) {
|
||||
const char *entry;
|
||||
if ((entry = critbit0_get(&g_commandv, mkcmdquery(name, namelen, scratch)))) {
|
||||
return &entry[namelen + 1];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
noinline static const char *findcmdpath(const char *name,
|
||||
char pathname[hasatleast PATH_MAX]) {
|
||||
char *p;
|
||||
int rc, olderr;
|
||||
size_t len;
|
||||
olderr = errno;
|
||||
if (!(len = strlen(name))) return PROGN(enoent(), NULL);
|
||||
if (memchr(name, '=', len)) return PROGN(einval(), NULL);
|
||||
if ((p = getcmdcache(name, len, pathname)) ||
|
||||
(((IsWindows() &&
|
||||
((rc = accesscmd(pathname, kNtSystemDirectory, name, len)) != -1 ||
|
||||
(rc = accesscmd(pathname, kNtWindowsDirectory, name, len)) != -1)) ||
|
||||
(rc = accesscmd(pathname, "", name, len)) != -1 ||
|
||||
(!strpbrk(name, "/\\") &&
|
||||
(rc = searchcmdpath(pathname, name, len)) != -1)) &&
|
||||
(p = cachecmd(name, len, pathname, rc)))) {
|
||||
errno = olderr;
|
||||
return p;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves pathname of executable.
|
||||
*
|
||||
* This does the same thing as `command -v` in bourne shell. Path
|
||||
* lookups are cached for the lifetime of the process. Paths with
|
||||
* multiple components will skip the resolution process. Undotted
|
||||
* basenames get automatic .com and .exe suffix resolution on all
|
||||
* platforms. Windows' system directories will always trump PATH.
|
||||
*
|
||||
* @return execve()'able path, or NULL w/ errno
|
||||
* @errno ENOENT, EACCES, ENOMEM
|
||||
* @see free(), execvpe()
|
||||
*/
|
||||
const char *commandv(const char *name) {
|
||||
char pathname[PATH_MAX];
|
||||
return findcmdpath(name, pathname);
|
||||
}
|
||||
190
libc/calls/hefty/dirstream.c
Normal file
190
libc/calls/hefty/dirstream.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/progn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/win32finddata.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/dt.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
struct dirstream {
|
||||
int64_t tell;
|
||||
int64_t fd;
|
||||
union {
|
||||
struct {
|
||||
unsigned buf_pos;
|
||||
unsigned buf_end;
|
||||
char buf[BUFSIZ];
|
||||
};
|
||||
struct {
|
||||
struct dirent winent;
|
||||
char __d_name[PATH_MAX];
|
||||
bool isdone;
|
||||
struct NtWin32FindData windata;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
static textwindows noinline DIR *opendir$nt(const char *name) {
|
||||
int len;
|
||||
DIR *res;
|
||||
char16_t name16[PATH_MAX];
|
||||
if ((len = mkntpath(name, name16)) == -1) return NULL;
|
||||
if (len + 2 + 1 > PATH_MAX) return PROGN(enametoolong(), NULL);
|
||||
if (name16[len - 1] == u'/' || name16[len - 1] == u'\\') {
|
||||
name16[--len] = u'\0';
|
||||
}
|
||||
name16[len++] = u'/';
|
||||
name16[len++] = u'*';
|
||||
name16[len] = u'\0';
|
||||
if (!(res = calloc(1, sizeof(DIR)))) return NULL;
|
||||
if ((res->fd = FindFirstFile(name16, &res->windata)) != -1) {
|
||||
return res;
|
||||
} else {
|
||||
winerr();
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens directory so readdir() and closedir() may be called.
|
||||
*
|
||||
* @returns newly allocated DIR object, or NULL w/ errno
|
||||
* @errors ENOENT, ENOTDIR, EACCES, EMFILE, ENFILE, ENOMEM
|
||||
*/
|
||||
DIR *opendir(const char *name) {
|
||||
if (!IsWindows() && !IsXnu()) {
|
||||
int fd;
|
||||
DIR *res = NULL;
|
||||
if ((fd = open(name, O_RDONLY | O_DIRECTORY | O_CLOEXEC, 0)) != -1) {
|
||||
if (!(res = fdopendir(fd))) close(fd);
|
||||
}
|
||||
return res;
|
||||
} else if (IsWindows()) {
|
||||
return opendir$nt(name);
|
||||
} else {
|
||||
enosys(); /* TODO(jart): Implement me! */
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates directory object for file descriptor.
|
||||
*
|
||||
* @param fd gets owned by this function, if it succeeds
|
||||
* @return new directory object, which must be freed by closedir(),
|
||||
* or NULL w/ errno
|
||||
* @errors ENOMEM and fd is closed
|
||||
*/
|
||||
DIR *fdopendir(int fd) {
|
||||
if (!IsWindows() && !IsXnu()) {
|
||||
DIR *dir;
|
||||
if ((dir = calloc(1, sizeof(*dir)))) {
|
||||
dir->fd = fd;
|
||||
return dir;
|
||||
}
|
||||
} else {
|
||||
enosys(); /* TODO(jart): Implement me! */
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads next entry from DIR.
|
||||
*
|
||||
* This API doesn't define any particular ordering.
|
||||
*
|
||||
* @param dir is the object opendir() or fdopendir() returned
|
||||
* @return next entry or NULL on end or error, which can be
|
||||
* differentiated by setting errno to 0 beforehand
|
||||
*/
|
||||
struct dirent *readdir(DIR *dir) {
|
||||
if (!IsWindows()) {
|
||||
if (dir->buf_pos >= dir->buf_end) {
|
||||
int rc;
|
||||
if (!(rc = getdents(dir->fd, dir->buf, BUFSIZ)) || rc == -1) {
|
||||
return NULL;
|
||||
}
|
||||
dir->buf_pos = 0;
|
||||
dir->buf_end = rc;
|
||||
}
|
||||
/* TODO(jart): Check FreeBSD and OpenBSD again regarding this */
|
||||
char *record = dir->buf + dir->buf_pos;
|
||||
char *name = record + 8 + 8 + 2;
|
||||
size_t namelen = strlen(name);
|
||||
unsigned char dtype = name[namelen + 1];
|
||||
memmove(name + 1, name, namelen + 1); /* shove forward one byte */
|
||||
*name = dtype; /* is dirent d_type field */
|
||||
struct dirent *ent = (void *)record;
|
||||
dir->buf_pos += ent->d_reclen;
|
||||
dir->tell = ent->d_off;
|
||||
return ent;
|
||||
} else {
|
||||
if (dir->isdone) return NULL;
|
||||
struct dirent *ent = &dir->winent;
|
||||
memset(ent, 0, sizeof(*ent));
|
||||
ent->d_reclen =
|
||||
sizeof(*ent) +
|
||||
tprecode16to8(ent->d_name, PATH_MAX, dir->windata.cFileName) + 1;
|
||||
dir->isdone = FindNextFile(dir->fd, &dir->windata);
|
||||
return ent;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes directory object returned by opendir().
|
||||
* @return 0 on success or -1 w/ errno
|
||||
*/
|
||||
int closedir(DIR *dir) {
|
||||
int rc;
|
||||
if (dir) {
|
||||
if (!IsWindows()) {
|
||||
rc = close(dir->fd);
|
||||
} else {
|
||||
rc = FindClose(dir->fd) ? 0 : winerr();
|
||||
}
|
||||
free(dir);
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current byte offset into directory data.
|
||||
*/
|
||||
long telldir(DIR *dir) {
|
||||
return dir->tell;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns file descriptor associated with DIR object.
|
||||
*/
|
||||
int dirfd(DIR *dir) {
|
||||
return dir->fd;
|
||||
}
|
||||
47
libc/calls/hefty/execl.c
Normal file
47
libc/calls/hefty/execl.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Executes program, with current environment.
|
||||
*
|
||||
* The current process is replaced with the executed one.
|
||||
*
|
||||
* @param prog will not be PATH searched, see execlp()
|
||||
* @param arg[0] is the name of the program to run
|
||||
* @param arg[1,n-2] optionally specify program arguments
|
||||
* @param arg[n-1] is NULL
|
||||
* @return doesn't return on success, otherwise -1 w/ errno
|
||||
* @notasyncsignalsafe (TODO)
|
||||
*/
|
||||
int execl(const char *exe, const char *arg, ... /*, NULL*/) {
|
||||
va_list va;
|
||||
void *argv;
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
execve(exe, argv, environ);
|
||||
free(argv);
|
||||
}
|
||||
va_end(va);
|
||||
return -1;
|
||||
}
|
||||
48
libc/calls/hefty/execle.c
Normal file
48
libc/calls/hefty/execle.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Executes program, with custom environment.
|
||||
*
|
||||
* The current process is replaced with the executed one.
|
||||
*
|
||||
* @param prog will not be PATH searched, see commandv()
|
||||
* @param arg[0] is the name of the program to run
|
||||
* @param arg[1,n-3] optionally specify program arguments
|
||||
* @param arg[n-2] is NULL
|
||||
* @param arg[n-1] is a pointer to a ["key=val",...,NULL] array
|
||||
* @return doesn't return on success, otherwise -1 w/ errno
|
||||
* @notasyncsignalsafe (TODO)
|
||||
*/
|
||||
int execle(const char *exe, const char *arg,
|
||||
... /*, NULL, char *const envp[] */) {
|
||||
va_list va;
|
||||
void *argv;
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
execve(exe, argv, va_arg(va, char *const *));
|
||||
free(argv);
|
||||
}
|
||||
va_end(va);
|
||||
return -1;
|
||||
}
|
||||
50
libc/calls/hefty/execlp.c
Normal file
50
libc/calls/hefty/execlp.c
Normal file
@@ -0,0 +1,50 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Executes program, with PATH search and current environment.
|
||||
*
|
||||
* The current process is replaced with the executed one.
|
||||
*
|
||||
* @param prog is program to launch (may be PATH searched)
|
||||
* @param arg[0] is the name of the program to run
|
||||
* @param arg[1,n-2] optionally specify program arguments
|
||||
* @param arg[n-1] is NULL
|
||||
* @return doesn't return on success, otherwise -1 w/ errno
|
||||
* @notasyncsignalsafe
|
||||
*/
|
||||
int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
||||
char *exe;
|
||||
if ((exe = commandv(prog))) {
|
||||
va_list va;
|
||||
void *argv;
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
execve(exe, argv, environ);
|
||||
free(argv);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
29
libc/calls/hefty/execv.c
Normal file
29
libc/calls/hefty/execv.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Replaces process with specific program, using default environment.
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int execv(const char *exe, char *const argv[]) {
|
||||
return execve(exe, argv, environ);
|
||||
}
|
||||
55
libc/calls/hefty/execve-nt.c
Normal file
55
libc/calls/hefty/execve-nt.c
Normal file
@@ -0,0 +1,55 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/startupinfo.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
|
||||
static textwindows int64_t passstdhand$nt(int fd) {
|
||||
if (g_fds.p[fd].kind != kFdEmpty &&
|
||||
!(g_fds.p[fd].flags &
|
||||
(g_fds.p[fd].kind == kFdSocket ? SOCK_CLOEXEC : O_CLOEXEC))) {
|
||||
return g_fds.p[fd].handle;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
textwindows int execve$nt(const char *program, char *const argv[],
|
||||
char *const envp[]) {
|
||||
struct NtStartupInfo startinfo;
|
||||
memset(&startinfo, 0, sizeof(startinfo));
|
||||
startinfo.cb = sizeof(struct NtStartupInfo);
|
||||
startinfo.dwFlags = kNtStartfUsestdhandles;
|
||||
startinfo.hStdInput = passstdhand$nt(STDIN_FILENO);
|
||||
startinfo.hStdOutput = passstdhand$nt(STDOUT_FILENO);
|
||||
startinfo.hStdError = passstdhand$nt(STDERR_FILENO);
|
||||
if (ntspawn(program, argv, envp, NULL, NULL, true, 0, NULL, &startinfo,
|
||||
NULL) != -1) {
|
||||
for (;;) TerminateProcess(GetCurrentProcess(), 0);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
43
libc/calls/hefty/execve.c
Normal file
43
libc/calls/hefty/execve.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Replaces current process with program.
|
||||
*
|
||||
* @param program will not be PATH searched, see commandv()
|
||||
* @param argv[0] is the name of the program to run
|
||||
* @param argv[1,n-2] optionally specify program arguments
|
||||
* @param argv[n-1] is NULL
|
||||
* @param envp[0,n-2] specifies "foo=bar" environment variables
|
||||
* @param envp[n-1] is NULL
|
||||
* @return doesn't return, or -1 w/ errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int execve(const char *program, char *const argv[], char *const envp[]) {
|
||||
if (!IsWindows()) {
|
||||
return execve$sysv(program, argv, envp);
|
||||
} else {
|
||||
return execve$nt(program, argv, envp);
|
||||
}
|
||||
}
|
||||
29
libc/calls/hefty/execvp.c
Normal file
29
libc/calls/hefty/execvp.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Replaces process, with path search, using default environment.
|
||||
* @notasyncsignalsafe
|
||||
*/
|
||||
int execvp(const char *file, char *const argv[]) {
|
||||
return execvpe(file, argv, environ);
|
||||
}
|
||||
40
libc/calls/hefty/execvpe.c
Normal file
40
libc/calls/hefty/execvpe.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Executes program, with path environment search.
|
||||
*
|
||||
* The current process is replaced with the executed one.
|
||||
*
|
||||
* @param prog is the program to launch
|
||||
* @param argv is [file,argv₁..argvₙ₋₁,NULL]
|
||||
* @param envp is ["key=val",...,NULL]
|
||||
* @return doesn't return on success, otherwise -1 w/ errno
|
||||
* @notasyncsignalsafe
|
||||
*/
|
||||
int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
||||
char *exe;
|
||||
if ((exe = commandv(prog))) {
|
||||
execve(exe, argv, envp);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
44
libc/calls/hefty/faccessat.c
Normal file
44
libc/calls/hefty/faccessat.c
Normal file
@@ -0,0 +1,44 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Checks if effective user can access path in particular ways.
|
||||
*
|
||||
* @param dirfd is usually AT_FDCWD
|
||||
* @param path is a filename or directory
|
||||
* @param flags can be R_OK, W_OK, X_OK, F_OK
|
||||
* @return 0 if ok, or -1 and sets errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int faccessat(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
if (!IsWindows()) {
|
||||
return faccessat$sysv(dirfd, path, mode, flags);
|
||||
} else {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (dirfd != AT_FDCWD || flags) return einval();
|
||||
if (mkntpath(path, path16) == -1) return -1;
|
||||
return ntaccesscheck(path16, mode);
|
||||
}
|
||||
}
|
||||
78
libc/calls/hefty/filecmp.c
Normal file
78
libc/calls/hefty/filecmp.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/map.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
static void *filecmp$mmap(int fd, size_t size) {
|
||||
return size ? mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares contents of files with memcmp().
|
||||
*
|
||||
* @return ≤0, 0, or ≥0 based on comparison; or ≠0 on error, in which
|
||||
* case we make our best effort to sift failing filenames rightward,
|
||||
* and errno can be set to 0 beforehand to differentiate errors
|
||||
*/
|
||||
int filecmp(const char *pathname1, const char *pathname2) {
|
||||
int res, olderr;
|
||||
int fd1 = -1;
|
||||
int fd2 = -1;
|
||||
char *addr1 = MAP_FAILED;
|
||||
char *addr2 = MAP_FAILED;
|
||||
size_t size1 = 0;
|
||||
size_t size2 = 0;
|
||||
if ((fd1 = open(pathname1, O_RDONLY)) != -1 &&
|
||||
(fd2 = open(pathname2, O_RDONLY)) != -1 &&
|
||||
(size1 = getfiledescriptorsize(fd1)) != -1 &&
|
||||
(size2 = getfiledescriptorsize(fd2)) != -1 &&
|
||||
(addr1 = filecmp$mmap(fd1, size1)) != MAP_FAILED &&
|
||||
(addr2 = filecmp$mmap(fd2, size2)) != MAP_FAILED) {
|
||||
olderr = errno;
|
||||
madvise(addr1, size1, MADV_WILLNEED | MADV_SEQUENTIAL);
|
||||
madvise(addr2, size2, MADV_WILLNEED | MADV_SEQUENTIAL);
|
||||
errno = olderr;
|
||||
res = memcmp(addr1, addr2, min(size1, size2));
|
||||
if (!res && size1 != size2) {
|
||||
char kNul = '\0';
|
||||
if (size1 > size2) {
|
||||
res = cmpub(addr1 + size2, &kNul);
|
||||
} else {
|
||||
res = cmpub(addr2 + size1, &kNul);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = cmpuq(&fd1, &fd2) | 1;
|
||||
}
|
||||
olderr = errno;
|
||||
munmap(addr1, size1);
|
||||
munmap(addr2, size2);
|
||||
close(fd1);
|
||||
close(fd2);
|
||||
errno = olderr;
|
||||
return res;
|
||||
}
|
||||
40
libc/calls/hefty/get_current_dir_name.c
Normal file
40
libc/calls/hefty/get_current_dir_name.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Returns current working directory.
|
||||
*
|
||||
* If the PWD environment variable is set, that'll be returned (since
|
||||
* it's faster than issuing a system call).
|
||||
*
|
||||
* @return pointer that must be free()'d, or NULL w/ errno
|
||||
*/
|
||||
nodiscard char *get_current_dir_name(void) {
|
||||
char *buf, *res;
|
||||
if ((res = getenv("PWD"))) return strdup(res);
|
||||
if (!(buf = malloc(PATH_MAX))) return NULL;
|
||||
if (!(res = (getcwd)(buf, PATH_MAX))) free(buf);
|
||||
return res;
|
||||
}
|
||||
73
libc/calls/hefty/hefty.mk
Normal file
73
libc/calls/hefty/hefty.mk
Normal file
@@ -0,0 +1,73 @@
|
||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Cosmopolitan System Call Compatibility Layer
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# This subpackage exports functions traditionally understood as system
|
||||
# calls that Cosmopolitan needs to wrap in a nontrivial way, requiring
|
||||
# things like dynamic memory allocation.
|
||||
|
||||
PKGS += LIBC_CALLS_HEFTY
|
||||
|
||||
LIBC_CALLS_HEFTY_ARTIFACTS += LIBC_CALLS_HEFTY_A
|
||||
LIBC_CALLS_HEFTY = $(LIBC_CALLS_HEFTY_A_DEPS) $(LIBC_CALLS_HEFTY_A)
|
||||
LIBC_CALLS_HEFTY_A = o/$(MODE)/libc/calls/hefty/hefty.a
|
||||
LIBC_CALLS_HEFTY_A_FILES := $(wildcard libc/calls/hefty/*)
|
||||
LIBC_CALLS_HEFTY_A_HDRS = $(filter %.h,$(LIBC_CALLS_HEFTY_A_FILES))
|
||||
LIBC_CALLS_HEFTY_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_HEFTY_A_FILES))
|
||||
LIBC_CALLS_HEFTY_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_HEFTY_A_FILES))
|
||||
|
||||
LIBC_CALLS_HEFTY_A_SRCS = \
|
||||
$(LIBC_CALLS_HEFTY_A_SRCS_S) \
|
||||
$(LIBC_CALLS_HEFTY_A_SRCS_C)
|
||||
|
||||
LIBC_CALLS_HEFTY_A_OBJS = \
|
||||
$(LIBC_CALLS_HEFTY_A_SRCS:%=o/$(MODE)/%.zip.o) \
|
||||
$(LIBC_CALLS_HEFTY_A_SRCS_S:%.S=o/$(MODE)/%.o) \
|
||||
$(LIBC_CALLS_HEFTY_A_SRCS_C:%.c=o/$(MODE)/%.o)
|
||||
|
||||
LIBC_CALLS_HEFTY_A_CHECKS = \
|
||||
$(LIBC_CALLS_HEFTY_A).pkg \
|
||||
$(LIBC_CALLS_HEFTY_A_HDRS:%=o/$(MODE)/%.ok)
|
||||
|
||||
LIBC_CALLS_HEFTY_A_DIRECTDEPS = \
|
||||
LIBC_ALG \
|
||||
LIBC_CONV \
|
||||
LIBC_FMT \
|
||||
LIBC_MEM \
|
||||
LIBC_STR \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_CALLS \
|
||||
LIBC_STUBS \
|
||||
LIBC_NT_KERNELBASE \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_SYSV
|
||||
|
||||
LIBC_CALLS_HEFTY_A_DEPS := \
|
||||
$(call uniq,$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(LIBC_CALLS_HEFTY_A): \
|
||||
libc/calls/hefty/ \
|
||||
$(LIBC_CALLS_HEFTY_A).pkg \
|
||||
$(LIBC_CALLS_HEFTY_A_OBJS)
|
||||
|
||||
$(LIBC_CALLS_HEFTY_A).pkg: \
|
||||
$(LIBC_CALLS_HEFTY_A_OBJS) \
|
||||
$(foreach x,$(LIBC_CALLS_HEFTY_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
LIBC_CALLS_HEFTY_LIBS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)))
|
||||
LIBC_CALLS_HEFTY_SRCS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_SRCS))
|
||||
LIBC_CALLS_HEFTY_HDRS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_HDRS))
|
||||
LIBC_CALLS_HEFTY_BINS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_BINS))
|
||||
LIBC_CALLS_HEFTY_CHECKS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_CHECKS))
|
||||
LIBC_CALLS_HEFTY_OBJS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_OBJS))
|
||||
LIBC_CALLS_HEFTY_TESTS = $(foreach x,$(LIBC_CALLS_HEFTY_ARTIFACTS),$($(x)_TESTS))
|
||||
$(LIBC_CALLS_HEFTY_OBJS): $(BUILD_FILES) libc/calls/hefty/hefty.mk
|
||||
|
||||
.PHONY: o/$(MODE)/libc/calls/hefty
|
||||
o/$(MODE)/libc/calls/hefty: $(LIBC_CALLS_HEFTY_CHECKS)
|
||||
14
libc/calls/hefty/internal.h
Normal file
14
libc/calls/hefty/internal.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int execve$nt(const char *, char *const[], char *const[]) hidden;
|
||||
int spawnve$nt(unsigned, int[3], const char *, char *const[],
|
||||
char *const[]) hidden;
|
||||
int spawnve$sysv(unsigned, int[3], const char *, char *const[],
|
||||
char *const[]) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_INTERNAL_H_ */
|
||||
98
libc/calls/hefty/mkntcmdline.c
Normal file
98
libc/calls/hefty/mkntcmdline.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nexgen32e/hascharacter.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define APPENDCHAR(C) \
|
||||
do { \
|
||||
if (mkntcmdline_append(&cmdline_p, &cmdline_i, &cmdline_n, C) == -1) { \
|
||||
goto error; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static int mkntcmdline_append(char16_t **p, size_t *i, size_t *n, char16_t c) {
|
||||
return APPEND(p, i, n, &c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts System V argv to Windows-style command line.
|
||||
*
|
||||
* Escaping is performed and it's designed to round-trip with
|
||||
* getdosargv() or getdosargv(). This function does NOT escape
|
||||
* command interpreter syntax, e.g. $VAR (sh), %VAR% (cmd).
|
||||
*
|
||||
* @param argv is an a NULL-terminated array of UTF-8 strings
|
||||
* @return freshly allocated lpCommandLine or NULL w/ errno
|
||||
* @kudos Daniel Colascione for teaching how to quote
|
||||
* @see libc/runtime/dosargv.c
|
||||
*/
|
||||
hidden textwindows nodiscard char16_t *mkntcmdline(char *const argv[]) {
|
||||
wint_t wc;
|
||||
size_t i, j;
|
||||
char16_t cbuf[2];
|
||||
char16_t *cmdline_p = NULL;
|
||||
size_t cmdline_i = 0;
|
||||
size_t cmdline_n = 0;
|
||||
if (argv[0]) {
|
||||
for (i = 0; argv[i]; ++i) {
|
||||
if (i) APPENDCHAR(u' ');
|
||||
bool needsquote = !argv[i] || !!argv[i][strcspn(argv[i], " \t\n\v\"")];
|
||||
if (needsquote) APPENDCHAR(u'"');
|
||||
for (j = 0;;) {
|
||||
if (needsquote) {
|
||||
int slashes = 0;
|
||||
while (argv[i][j] && argv[i][j] == u'\\') slashes++, j++;
|
||||
slashes <<= 1;
|
||||
if (argv[i][j] == u'"') slashes++;
|
||||
while (slashes--) APPENDCHAR(u'\\');
|
||||
}
|
||||
if (!argv[i][j]) break;
|
||||
j += abs(tpdecode(&argv[i][j], &wc));
|
||||
if (CONCAT(&cmdline_p, &cmdline_i, &cmdline_n, cbuf,
|
||||
abs(pututf16(cbuf, ARRAYLEN(cbuf), wc, false))) == -1) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (needsquote) APPENDCHAR(u'"');
|
||||
}
|
||||
APPENDCHAR(u'\0');
|
||||
if (cmdline_i > CMD_MAX) {
|
||||
e2big();
|
||||
goto error;
|
||||
}
|
||||
} else {
|
||||
einval();
|
||||
}
|
||||
return cmdline_p;
|
||||
error:
|
||||
free(cmdline_p);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef APPENDCHAR
|
||||
69
libc/calls/hefty/mkntenvblock.c
Normal file
69
libc/calls/hefty/mkntenvblock.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Copies sorted environment variable block for Windows.
|
||||
*
|
||||
* This is designed to meet the requirements of CreateProcess().
|
||||
*
|
||||
* @param envp is an a NULL-terminated array of UTF-8 strings
|
||||
* @return freshly allocated lpEnvironment or NULL w/ errno
|
||||
*/
|
||||
textwindows char16_t *mkntenvblock(char *const envp[]) {
|
||||
size_t block_i = 0;
|
||||
size_t block_n = 0;
|
||||
char16_t *block_p = NULL;
|
||||
size_t i, j;
|
||||
if (!(envp = sortenvp(envp))) goto error;
|
||||
const char16_t kNul = u'\0';
|
||||
for (i = 0; envp[i]; ++i) {
|
||||
unsigned consumed;
|
||||
for (j = 0;; j += consumed) {
|
||||
wint_t wc;
|
||||
char16_t cbuf[2];
|
||||
consumed = abs(tpdecode(&envp[i][j], &wc));
|
||||
if (CONCAT(&block_p, &block_i, &block_n, cbuf,
|
||||
abs(pututf16(cbuf, ARRAYLEN(cbuf), wc, false))) == -1) {
|
||||
goto error;
|
||||
}
|
||||
if (!wc) break;
|
||||
}
|
||||
}
|
||||
if (APPEND(&block_p, &block_i, &block_n, &kNul) == -1) {
|
||||
goto error;
|
||||
}
|
||||
if (block_i > ENV_MAX) {
|
||||
e2big();
|
||||
goto error;
|
||||
}
|
||||
free(envp);
|
||||
return block_p;
|
||||
error:
|
||||
free(envp);
|
||||
free(block_p);
|
||||
return NULL;
|
||||
}
|
||||
32
libc/calls/hefty/mkvarargv.h
Normal file
32
libc/calls/hefty/mkvarargv.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/**
|
||||
* Turns variadic program arguments into array.
|
||||
*
|
||||
* This is a support function for execl(), execlp(), spawnl(), etc.
|
||||
*
|
||||
* @note type signatures are fubar for these functions
|
||||
*/
|
||||
forceinline void *mkvarargv(const char *arg1, va_list va) {
|
||||
size_t i, n;
|
||||
const char **p, *arg;
|
||||
i = 0;
|
||||
n = 0;
|
||||
p = NULL;
|
||||
arg = arg1;
|
||||
do {
|
||||
if (APPEND(&p, &i, &n, &arg) == -1) {
|
||||
free(p);
|
||||
return NULL;
|
||||
}
|
||||
} while ((arg = va_arg(va, const char *)));
|
||||
return p;
|
||||
}
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_MKVARARGV_H_ */
|
||||
87
libc/calls/hefty/ntaccesscheck.c
Normal file
87
libc/calls/hefty/ntaccesscheck.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/enum/accessmask.h"
|
||||
#include "libc/nt/enum/securityinformation.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/genericmapping.h"
|
||||
#include "libc/nt/struct/privilegeset.h"
|
||||
#include "libc/nt/struct/securitydescriptor.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
|
||||
/**
|
||||
* Checks if current process has access to folder or file.
|
||||
*
|
||||
* @param flags can have R_OK, W_OK, X_OK, etc.
|
||||
* @return 0 if authorized, or -1 w/ errno
|
||||
* @kudos Aaron Ballman for teaching how to do this
|
||||
* @see libc/sysv/consts.sh
|
||||
*/
|
||||
textwindows int ntaccesscheck(const char16_t *pathname, uint32_t flags) {
|
||||
int rc;
|
||||
bool32 result;
|
||||
int64_t hToken, hImpersonatedToken;
|
||||
uint32_t secsize, granted, privsize;
|
||||
struct NtPrivilegeSet privileges;
|
||||
struct NtGenericMapping mapping;
|
||||
struct NtSecurityDescriptor security;
|
||||
struct NtSecurityDescriptor *psecurity;
|
||||
const uint32_t request = kNtOwnerSecurityInformation |
|
||||
kNtGroupSecurityInformation |
|
||||
kNtDaclSecurityInformation;
|
||||
granted = 0;
|
||||
result = false;
|
||||
psecurity = &security;
|
||||
secsize = sizeof(security);
|
||||
privsize = sizeof(privileges);
|
||||
memset(&privileges, 0, sizeof(privileges));
|
||||
mapping.GenericRead = kNtFileGenericRead;
|
||||
mapping.GenericWrite = kNtFileGenericWrite;
|
||||
mapping.GenericExecute = kNtFileGenericExecute;
|
||||
mapping.GenericAll = kNtFileAllAccess;
|
||||
MapGenericMask(&flags, &mapping);
|
||||
hImpersonatedToken = hToken = -1;
|
||||
if ((GetFileSecurity(pathname, request, psecurity, 0, &secsize) ||
|
||||
(GetLastError() == kNtErrorInsufficientBuffer &&
|
||||
(psecurity = malloc(secsize)) &&
|
||||
GetFileSecurity(pathname, request, psecurity, secsize, &secsize))) &&
|
||||
OpenProcessToken(GetCurrentProcess(),
|
||||
kNtTokenImpersonate | kNtTokenQuery | kNtTokenDuplicate |
|
||||
kNtStandardRightsRead,
|
||||
&hToken) &&
|
||||
DuplicateToken(hToken, kNtSecurityImpersonation, &hImpersonatedToken) &&
|
||||
AccessCheck(psecurity, hImpersonatedToken, flags, &mapping, &privileges,
|
||||
&privsize, &granted, &result) &&
|
||||
(result || flags == F_OK)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = winerr();
|
||||
}
|
||||
free_s(&psecurity);
|
||||
close(hImpersonatedToken);
|
||||
close(hToken);
|
||||
return rc;
|
||||
}
|
||||
88
libc/calls/hefty/ntspawn.c
Normal file
88
libc/calls/hefty/ntspawn.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Spawns process on Windows NT.
|
||||
*
|
||||
* This function delegates to CreateProcess() with UTF-8 → UTF-16
|
||||
* translation and argv escaping. Please note this will NOT escape
|
||||
* command interpreter syntax.
|
||||
*
|
||||
* @param program will not be PATH searched, see commandv()
|
||||
* @param argv[0] is the name of the program to run
|
||||
* @param argv[1,n-2] optionally specifies program arguments
|
||||
* @param argv[n-1] is NULL
|
||||
* @param envp[𝟶,m-2] specifies "foo=bar" environment variables, which
|
||||
* don't need to be passed in sorted order; however, this function
|
||||
* goes faster the closer they are to sorted
|
||||
* @param envp[m-1] is NULL
|
||||
* @param bInheritHandles means handles already marked inheritable will
|
||||
* be inherited; which, assuming the System V wrapper functions are
|
||||
* being used, should mean (1) all files and sockets that weren't
|
||||
* opened with O_CLOEXEC; and (2) all memory mappings
|
||||
* @param opt_out_lpProcessInformation can be used to return process and
|
||||
* thread IDs to parent, as well as open handles that need close()
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @see spawnve() which abstracts this function
|
||||
*/
|
||||
textwindows int ntspawn(
|
||||
const char *program, char *const argv[], char *const envp[],
|
||||
struct NtSecurityAttributes *opt_lpProcessAttributes,
|
||||
struct NtSecurityAttributes *opt_lpThreadAttributes, bool32 bInheritHandles,
|
||||
uint32_t dwCreationFlags, const char16_t *opt_lpCurrentDirectory,
|
||||
/*nodiscard*/ const struct NtStartupInfo *lpStartupInfo,
|
||||
struct NtProcessInformation *opt_out_lpProcessInformation) {
|
||||
int rc;
|
||||
char16_t program16[PATH_MAX], *lpCommandLine, *lpEnvironment;
|
||||
lpCommandLine = NULL;
|
||||
lpEnvironment = NULL;
|
||||
if (mkntpath(program, program16) != -1 &&
|
||||
(lpCommandLine = mkntcmdline(argv)) &&
|
||||
(lpEnvironment = mkntenvblock(envp))) {
|
||||
if (CreateProcess(program16, lpCommandLine, opt_lpProcessAttributes,
|
||||
opt_lpThreadAttributes, bInheritHandles,
|
||||
dwCreationFlags | kNtCreateUnicodeEnvironment,
|
||||
lpEnvironment, opt_lpCurrentDirectory, lpStartupInfo,
|
||||
opt_out_lpProcessInformation)) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = winerr();
|
||||
}
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
free(lpCommandLine);
|
||||
free(lpEnvironment);
|
||||
return rc;
|
||||
}
|
||||
20
libc/calls/hefty/ntspawn.h
Normal file
20
libc/calls/hefty/ntspawn.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct NtProcessInformation;
|
||||
struct NtSecurityAttributes;
|
||||
struct NtStartupInfo;
|
||||
|
||||
char **sortenvp(char *const[]) hidden nodiscard paramsnonnull();
|
||||
char16_t *mkntcmdline(char *const[]) hidden nodiscard paramsnonnull();
|
||||
char16_t *mkntenvblock(char *const[]) hidden nodiscard paramsnonnull();
|
||||
int ntspawn(const char *, char *const[], char *const[],
|
||||
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
|
||||
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,
|
||||
struct NtProcessInformation *) paramsnonnull((1, 2, 3, 9)) hidden;
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_NTSPAWN_H_ */
|
||||
49
libc/calls/hefty/replaceuser.c
Normal file
49
libc/calls/hefty/replaceuser.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/calls/calls.h"
|
||||
|
||||
/**
|
||||
* Replaces tilde in path w/ user home folder.
|
||||
*
|
||||
* @param path is NULL propagating
|
||||
* @return must be free()'d
|
||||
*/
|
||||
char *replaceuser(const char *path) {
|
||||
char *res, *p;
|
||||
const char *home;
|
||||
size_t pathlen, homelen;
|
||||
res = NULL;
|
||||
if (path && *path++ == '~' && !isempty((home = getenv("HOME")))) {
|
||||
while (*path == '/') path++;
|
||||
pathlen = strlen(path);
|
||||
homelen = strlen(home);
|
||||
while (homelen && home[homelen - 1] == '/') homelen--;
|
||||
if ((p = res = malloc(pathlen + 1 + homelen + 1))) {
|
||||
p = mempcpy(p, home, homelen);
|
||||
*p++ = '/';
|
||||
memcpy(p, path, pathlen + 1);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
89
libc/calls/hefty/slurp.c
Normal file
89
libc/calls/hefty/slurp.c
Normal file
@@ -0,0 +1,89 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/arraylist2.h"
|
||||
#include "libc/bits/safemacros.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
static size_t getfilesize(int fd) {
|
||||
struct stat st;
|
||||
st.st_size = 0;
|
||||
fstat(fd, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static size_t smudgefilesize(size_t size) {
|
||||
return roundup(size, PAGESIZE) + PAGESIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads entire file into memory.
|
||||
*
|
||||
* This function is fantastic for being lazy. It may waste space if the
|
||||
* file is large, but it's implemented in a conscientious way that won't
|
||||
* bomb the systemwide page cache. It means performance too, naturally.
|
||||
*
|
||||
* @return contents which must be free()'d or NULL w/ errno
|
||||
*/
|
||||
char *slurp(const char *path, size_t *opt_out_readlength) {
|
||||
int fd;
|
||||
ssize_t rc;
|
||||
char *res, *p;
|
||||
size_t i, n, got, want;
|
||||
res = NULL;
|
||||
if ((fd = open(path, O_RDONLY)) == -1) goto Failure;
|
||||
n = getfilesize(fd);
|
||||
/* TODO(jart): Fix this, it's totally broken */
|
||||
if (!(res = valloc(smudgefilesize(n)))) goto Failure;
|
||||
if (n > FRAMESIZE) fadvise(fd, 0, n, MADV_SEQUENTIAL);
|
||||
i = 0;
|
||||
for (;;) {
|
||||
want = smudgefilesize(n - i);
|
||||
TryAgain:
|
||||
if ((rc = read(fd, &res[i], want)) == -1) {
|
||||
if (errno == EINTR) goto TryAgain;
|
||||
goto Failure;
|
||||
}
|
||||
got = (size_t)rc;
|
||||
if (i + 1 >= n) {
|
||||
if ((p = realloc(res, smudgefilesize((n += n >> 1))))) {
|
||||
res = p;
|
||||
} else {
|
||||
goto Failure;
|
||||
}
|
||||
}
|
||||
i += got;
|
||||
if (got == 0) break;
|
||||
if (got > want) abort();
|
||||
}
|
||||
if (opt_out_readlength) *opt_out_readlength = i;
|
||||
res[i] = '\0';
|
||||
close(fd);
|
||||
return res;
|
||||
Failure:
|
||||
free(res);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
68
libc/calls/hefty/sortenvp.c
Normal file
68
libc/calls/hefty/sortenvp.c
Normal file
@@ -0,0 +1,68 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/alg/alg.h"
|
||||
#include "libc/alg/arraylist.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nexgen32e/tinystrcmp.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
static int sortenvpcb(const char **a, const char **b) { return strcmp(*a, *b); }
|
||||
|
||||
static void slowsort(char **a, int n) {
|
||||
size_t i, j;
|
||||
const char *t;
|
||||
for (i = 1; i < n; ++i) {
|
||||
j = i;
|
||||
t = a[i];
|
||||
while (j > 0 && tinystrcmp(t, a[j - 1]) < 0) {
|
||||
a[j] = a[j - 1];
|
||||
--j;
|
||||
}
|
||||
a[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies environment variable pointers and sorts them.
|
||||
*
|
||||
* This is useful for (a) binary searching; and (b) keeping the NT
|
||||
* Executive happy, which wants strings to be ordered by UNICODE
|
||||
* codepoint identifiers. That's basically what uint8_t comparisons on
|
||||
* UTF8-encoded data gives us.
|
||||
*
|
||||
* @param envp is a NULL-terminated string array
|
||||
* @return newly allocated sorted copy of envp pointer array
|
||||
*/
|
||||
hidden textwindows nodiscard char **sortenvp(char *const envp[]) {
|
||||
size_t count = 0;
|
||||
while (envp[count]) count++;
|
||||
size_t bytesize = (count + 1) * sizeof(char *);
|
||||
char **copy = malloc(bytesize);
|
||||
if (copy) {
|
||||
memcpy(copy, envp, bytesize);
|
||||
if (IsTiny()) {
|
||||
slowsort(copy, count);
|
||||
} else {
|
||||
qsort(copy, count, sizeof(char *), (void *)sortenvpcb);
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
26
libc/calls/hefty/spawn.h
Normal file
26
libc/calls/hefty/spawn.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_
|
||||
|
||||
#define SPAWN_DETACH 1
|
||||
#define SPAWN_TABULARASA 2
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int spawnve(unsigned, int[3], const char *, char *const[], char *const[])
|
||||
paramsnonnull((3, 4, 5));
|
||||
int spawnl(unsigned, int[3], const char *, const char *, ...) nullterminated()
|
||||
paramsnonnull((3, 4));
|
||||
int spawnlp(unsigned, int[3], const char *, const char *, ...) nullterminated()
|
||||
paramsnonnull((3, 4));
|
||||
int spawnle(unsigned, int[3], const char *, const char *, ...)
|
||||
nullterminated((1)) paramsnonnull((3, 4));
|
||||
int spawnv(unsigned, int[3], const char *, char *const[]) paramsnonnull((3, 4));
|
||||
int spawnvp(unsigned, int[3], const char *, char *const[])
|
||||
paramsnonnull((3, 4));
|
||||
int spawnvpe(unsigned, int[3], const char *, char *const[], char *const[])
|
||||
paramsnonnull((3, 4, 5));
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_HEFTY_SPAWN_H_ */
|
||||
49
libc/calls/hefty/spawnl.c
Normal file
49
libc/calls/hefty/spawnl.c
Normal file
@@ -0,0 +1,49 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Launches program, with current environment.
|
||||
*
|
||||
* @param stdiofds may optionally be passed to customize standard i/o
|
||||
* @param stdiofds[𝑖] may be -1 to receive a pipe() fd
|
||||
* @param prog is program to launch (may be PATH searched)
|
||||
* @param arg[0] is the name of the program to run
|
||||
* @param arg[1,n-2] optionally specify program arguments
|
||||
* @param arg[n-1] is NULL
|
||||
* @return pid of child, or -1 w/ errno
|
||||
*/
|
||||
int spawnl(unsigned flags, int stdiofds[3], const char *exe, const char *arg,
|
||||
... /*, NULL*/) {
|
||||
int rc;
|
||||
va_list va;
|
||||
void *argv;
|
||||
rc = -1;
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
rc = spawnve(flags, stdiofds, exe, argv, environ);
|
||||
free(argv);
|
||||
}
|
||||
va_end(va);
|
||||
return rc;
|
||||
}
|
||||
53
libc/calls/hefty/spawnlp.c
Normal file
53
libc/calls/hefty/spawnlp.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/mkvarargv.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Launches program, with PATH search and current environment.
|
||||
*
|
||||
* @param stdiofds may optionally be passed to customize standard i/o
|
||||
* @param stdiofds[𝑖] may be -1 to receive a pipe() fd
|
||||
* @param prog is program to launch (may be PATH searched)
|
||||
* @param arg[0] is the name of the program to run
|
||||
* @param arg[1,n-2] optionally specify program arguments
|
||||
* @param arg[n-1] is NULL
|
||||
* @return pid of child, or -1 w/ errno
|
||||
*/
|
||||
nodiscard int spawnlp(unsigned flags, int stdiofds[3], const char *prog,
|
||||
const char *arg, ... /*, NULL*/) {
|
||||
int pid;
|
||||
char *exe;
|
||||
va_list va;
|
||||
void *argv;
|
||||
pid = -1;
|
||||
if ((exe = commandv(prog))) {
|
||||
va_start(va, arg);
|
||||
if ((argv = mkvarargv(arg, va))) {
|
||||
pid = spawnve(flags, stdiofds, exe, argv, environ);
|
||||
free(argv);
|
||||
}
|
||||
va_end(va);
|
||||
}
|
||||
return pid;
|
||||
}
|
||||
98
libc/calls/hefty/spawnve-nt.c
Normal file
98
libc/calls/hefty/spawnve-nt.c
Normal file
@@ -0,0 +1,98 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/xchg.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/hefty/ntspawn.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/nt/enum/startf.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/startupinfo.h"
|
||||
#include "libc/nt/struct/processinformation.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
textwindows int spawnve$nt(unsigned flags, int stdiofds[3], const char *program,
|
||||
char *const argv[], char *const envp[]) {
|
||||
int pid;
|
||||
size_t i;
|
||||
int tubes[3];
|
||||
int64_t handle, h, *x, *y;
|
||||
struct NtStartupInfo sti;
|
||||
struct NtProcessInformation procinfo;
|
||||
|
||||
handle = 0;
|
||||
memset(&sti, 0, sizeof(sti));
|
||||
sti.cb = sizeof(sti);
|
||||
sti.dwFlags = kNtStartfUsestdhandles;
|
||||
|
||||
if ((pid = createfd()) == -1) return -1;
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (stdiofds[i] == -1) {
|
||||
x = &h;
|
||||
y = &sti.stdiofds[i];
|
||||
if (kIoMotion[i]) xchg(&x, &y);
|
||||
if ((tubes[i] = createfd()) != -1 &&
|
||||
CreatePipe(x, y, &kNtIsInheritable, 0)) {
|
||||
g_fds.p[tubes[i]].handle = h;
|
||||
} else {
|
||||
handle = -1;
|
||||
}
|
||||
} else {
|
||||
sti.stdiofds[i] = g_fds.p[stdiofds[i]].handle;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle != -1 &&
|
||||
ntspawn(program, argv, envp, NULL, NULL,
|
||||
(flags & SPAWN_TABULARASA) ? false : true,
|
||||
(flags & SPAWN_DETACH)
|
||||
? (kNtCreateNewProcessGroup | kNtDetachedProcess |
|
||||
kNtCreateBreakawayFromJob)
|
||||
: 0,
|
||||
NULL, &sti, &procinfo) != -1) {
|
||||
CloseHandle(procinfo.hThread);
|
||||
handle = procinfo.hProcess;
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (stdiofds[i] == -1) {
|
||||
if (handle != -1) {
|
||||
stdiofds[i] = tubes[i];
|
||||
g_fds.p[tubes[i]].kind = kFdFile;
|
||||
g_fds.p[tubes[i]].flags = O_CLOEXEC;
|
||||
CloseHandle(sti.stdiofds[i]);
|
||||
} else {
|
||||
CloseHandle(tubes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
g_fds.p[pid].kind = kFdProcess;
|
||||
g_fds.p[pid].handle = handle;
|
||||
g_fds.p[pid].flags = flags;
|
||||
return pid;
|
||||
}
|
||||
121
libc/calls/hefty/spawnve-sysv.c
Normal file
121
libc/calls/hefty/spawnve-sysv.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/conv/conv.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/paths.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
||||
int spawnve$sysv(unsigned flags, int stdiofds[3], const char *program,
|
||||
char *const argv[], char *const envp[]) {
|
||||
int rc, pid, fd;
|
||||
size_t i, j, len;
|
||||
int32_t tubes[3][2];
|
||||
char **argv2, MZqFpD[8];
|
||||
void *argv3;
|
||||
|
||||
pid = 0;
|
||||
argv2 = NULL;
|
||||
argv3 = argv;
|
||||
|
||||
/*
|
||||
* αcτµαlly pδrταblε εxεcµταblε w/ thompson shell script
|
||||
* morphology needs to be launched via command interpreter.
|
||||
*/
|
||||
if (endswith(program, ".com") || endswith(program, ".exe")) {
|
||||
memset(MZqFpD, 0, sizeof(MZqFpD));
|
||||
fd = openat$sysv(AT_FDCWD, program, O_RDONLY, 0);
|
||||
read$sysv(fd, MZqFpD, sizeof(MZqFpD));
|
||||
close$sysv(fd);
|
||||
if (memcmp(MZqFpD, "MZqFpD", 6) == 0) {
|
||||
/*
|
||||
* If we got this:
|
||||
*
|
||||
* spawn(/bin/echo, [echo, hi, there])
|
||||
*
|
||||
* It will become this:
|
||||
*
|
||||
* spawn(/bin/sh, [sh, /bin/echo, hi, there])
|
||||
*/
|
||||
len = 1;
|
||||
while (argv[len]) len++;
|
||||
if ((argv2 = malloc((2 + len + 1) * sizeof(char *)))) {
|
||||
i = 0, j = 1;
|
||||
argv2[i++] = "sh";
|
||||
argv2[i++] = program;
|
||||
while (j < len) argv2[i++] = argv[j++];
|
||||
argv2[i] = NULL;
|
||||
argv3 = argv2;
|
||||
program = "/bin/sh";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (stdiofds[i] == -1) {
|
||||
pid |= pipe$sysv(tubes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pid != -1) {
|
||||
if ((pid = fork$sysv()) == 0) {
|
||||
if (flags & SPAWN_DETACH) {
|
||||
if (setsid() == -1) abort();
|
||||
if ((rc = fork$sysv()) == -1) abort();
|
||||
if (rc > 0) _exit(0);
|
||||
}
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (stdiofds[i] == -1) {
|
||||
close$sysv(tubes[i][kIoMotion[i]]);
|
||||
fd = tubes[i][!kIoMotion[i]];
|
||||
} else {
|
||||
fd = stdiofds[i];
|
||||
}
|
||||
dup2$sysv(fd, i);
|
||||
}
|
||||
execve$sysv(program, argv3, envp);
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 3; ++i) {
|
||||
if (stdiofds[i] == -1) {
|
||||
close$sysv(tubes[i][!kIoMotion[i]]);
|
||||
fd = tubes[i][kIoMotion[i]];
|
||||
if (pid != -1) {
|
||||
stdiofds[i] = fd;
|
||||
} else {
|
||||
close$sysv(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (argv2) free(argv2);
|
||||
return pid;
|
||||
}
|
||||
63
libc/calls/hefty/spawnve.c
Normal file
63
libc/calls/hefty/spawnve.c
Normal file
@@ -0,0 +1,63 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/pushpop.h"
|
||||
#include "libc/calls/hefty/internal.h"
|
||||
#include "libc/calls/hefty/spawn.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/sysv/consts/fileno.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Launches program, e.g.
|
||||
*
|
||||
* char buf[2];
|
||||
* int ws, pid, fds[3] = {-1, -1, STDERR_FILENO};
|
||||
* CHECK_NE(-1, (pid = spawnve(0, fds, commandv("ssh"),
|
||||
* (char *const[]){"ssh", hostname, "cat", NULL},
|
||||
* environ)));
|
||||
* CHECK_EQ(+2, write(fds[0], "hi", 2));
|
||||
* CHECK_NE(-1, close(fds[0]));
|
||||
* CHECK_EQ(+2, read(fds[1], buf, 2)));
|
||||
* CHECK_NE(-1, close(fds[1]));
|
||||
* CHECK_EQ(+0, memcmp(buf, "hi", 2)));
|
||||
* CHECK_NE(-1, waitpid(pid, &ws, 0));
|
||||
* CHECK_EQ(+0, WEXITSTATUS(ws));
|
||||
*
|
||||
* @param stdiofds may optionally be passed to customize standard i/o
|
||||
* @param stdiofds[𝑖] may be -1 to receive a pipe() fd
|
||||
* @param program will not be PATH searched, see commandv()
|
||||
* @param argv[0] is the name of the program to run
|
||||
* @param argv[1,n-2] optionally specify program arguments
|
||||
* @param argv[n-1] is NULL
|
||||
* @param envp[0,n-2] specifies "foo=bar" environment variables
|
||||
* @param envp[n-1] is NULL
|
||||
* @return pid of child, or -1 w/ errno
|
||||
*/
|
||||
int spawnve(unsigned flags, int stdiofds[3], const char *program,
|
||||
char *const argv[], char *const envp[]) {
|
||||
if (!argv[0]) return einval();
|
||||
int defaultfds[3] = {pushpop(STDIN_FILENO), pushpop(STDOUT_FILENO),
|
||||
pushpop(STDERR_FILENO)};
|
||||
if (!IsWindows()) {
|
||||
return spawnve$sysv(flags, stdiofds ?: defaultfds, program, argv, envp);
|
||||
} else {
|
||||
return spawnve$nt(flags, stdiofds ?: defaultfds, program, argv, envp);
|
||||
}
|
||||
}
|
||||
29
libc/calls/hefty/ttyname.c
Normal file
29
libc/calls/hefty/ttyname.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/log/log.h"
|
||||
|
||||
static char ttyname_buf[PATH_MAX];
|
||||
|
||||
char *ttyname(int fd) {
|
||||
int rc = ttyname_r(fd, ttyname_buf, sizeof(ttyname_buf));
|
||||
if (rc != 0) return NULL;
|
||||
return &ttyname_buf[0];
|
||||
}
|
||||
86
libc/calls/hefty/ttyname_r.c
Normal file
86
libc/calls/hefty/ttyname_r.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ This program is free software; you can redistribute it and/or modify │
|
||||
│ it under the terms of the GNU General Public License as published by │
|
||||
│ the Free Software Foundation; version 2 of the License. │
|
||||
│ │
|
||||
│ This program is distributed in the hope that it will be useful, but │
|
||||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||||
│ General Public License for more details. │
|
||||
│ │
|
||||
│ You should have received a copy of the GNU General Public License │
|
||||
│ along with this program; if not, write to the Free Software │
|
||||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||||
│ 02110-1301 USA │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static textwindows noinline int ttyname$nt(int fd, char *buf, size_t size) {
|
||||
uint32_t mode;
|
||||
if (GetConsoleMode(g_fds.p[fd].handle, &mode)) {
|
||||
if (mode & kNtEnableVirtualTerminalInput) {
|
||||
strncpy(buf, "CONIN$", size);
|
||||
return 0;
|
||||
} else {
|
||||
strncpy(buf, "CONOUT$", size);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return enotty();
|
||||
}
|
||||
}
|
||||
|
||||
static int ttyname$freebsd(int fd, char *buf, size_t size) {
|
||||
const unsigned FIODGNAME = 2148558456;
|
||||
struct fiodgname_arg {
|
||||
int len;
|
||||
void *buf;
|
||||
} fg;
|
||||
fg.buf = buf;
|
||||
fg.len = size;
|
||||
if (ioctl$sysv(fd, FIODGNAME, &fg) != -1) return 0;
|
||||
return enotty();
|
||||
}
|
||||
|
||||
static int ttyname$linux(int fd, char *buf, size_t size) {
|
||||
struct stat st1, st2;
|
||||
if (!isatty(fd)) return errno;
|
||||
char name[PATH_MAX];
|
||||
snprintf(name, sizeof(name), "/proc/self/fd/%d", fd);
|
||||
ssize_t got;
|
||||
got = readlink(name, buf, size);
|
||||
if (got == -1) return errno;
|
||||
if ((size_t)got >= size) return erange();
|
||||
buf[got] = 0;
|
||||
if (stat(buf, &st1) || fstat(fd, &st2)) return errno;
|
||||
if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) return enodev();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ttyname_r(int fd, char *buf, size_t size) {
|
||||
if (IsLinux()) {
|
||||
return ttyname$linux(fd, buf, size);
|
||||
} else if (IsFreebsd()) {
|
||||
return ttyname$freebsd(fd, buf, size);
|
||||
} else if (IsWindows()) {
|
||||
if (isfdkind(fd, kFdFile)) {
|
||||
return ttyname$nt(fd, buf, size);
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
} else {
|
||||
return enosys();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user