Make improvements

- Expand redbean UNIX module
- Expand redbean documentation
- Ensure Lua copyright is embedded in binary
- Increase the PATH_MAX limit especially on NT
- Use column major sorting for linenoise completions
- Fix some suboptimalities in redbean's new UNIX API
- Figured out right flags for Multics newline in raw mode
This commit is contained in:
Justine Tunney 2022-04-24 09:59:22 -07:00
parent cf3174dc74
commit 2046c0d2ae
305 changed files with 6602 additions and 4221 deletions

Binary file not shown.

View file

@ -169,7 +169,7 @@ DEFAULT_LDFLAGS = \
--gc-sections \
--build-id=none \
--no-dynamic-linker \
-zmax-page-size=0x1000
-zmax-page-size=0x1000 #--cref -Map=$@.map
ZIPOBJ_FLAGS = \
-b$(IMAGE_BASE_VIRTUAL)

View file

@ -31,13 +31,6 @@ int ttysetraw(struct termios *conf, int64_t flags) {
conf->c_cflag &= ~(CSIZE | PARENB);
conf->c_cflag |= CS8;
conf->c_iflag |= IUTF8;
/* if (flags & kTtyLfToCrLf) { */
/* /\* conf->c_oflag &= ~(OLCUC | OCRNL | ONLRET | OFILL | OFDEL); *\/ */
/* /\* conf->c_oflag |= ONLCR | ONOCR; *\/ */
/* conf->c_oflag |= ONLCR; */
/* } else { */
/* conf->c_oflag &= ~OPOST; */
/* } */
if (!(flags & kTtySigs)) {
conf->c_iflag &= ~(IGNBRK | BRKINT);
conf->c_lflag &= ~(ISIG);

View file

@ -151,14 +151,6 @@ o/$(MODE)/examples/hello.com.dbg: \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/printargs.com.dbg: \
$(EXAMPLES_DEPS) \
o/$(MODE)/examples/printargs.o \
o/$(MODE)/examples/examples.pkg \
$(CRT) \
$(APE_NO_MODIFY_SELF)
@$(APELINK)
o/$(MODE)/examples/nesemu1.o: QUOTA += -M512m
$(EXAMPLES_OBJS): examples/examples.mk

View file

@ -7,30 +7,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ │
*/
#endif
#include "libc/bits/safemacros.internal.h"
#include "libc/calls/calls.h"
#include "libc/runtime/runtime.h"
int main() {
int pip[2];
char buf[PATH_MAX];
char *args[2] = {0};
if (strcmp(nulltoempty(getenv("TERM")), "dumb") && isatty(0) && isatty(1) &&
((args[0] = commandv("less", buf)) ||
(args[0] = commandv("more", buf)))) {
close(0);
close(2);
pipe(pip);
if (!vfork()) {
close(2);
execv(args[0], args);
_Exit(127);
}
close(0);
__printargs("");
close(2);
wait(0);
} else {
__printargs("");
}
__printargs("");
}

View file

@ -67,9 +67,9 @@ int main(int argc, char *argv[]) {
char *exepath;
struct rusage r;
long double real;
char exebuf[PATH_MAX];
char exebuf[PATH_MAX + 1];
if (argc >= 2) {
if ((exepath = commandv(argv[1], exebuf))) {
if ((exepath = commandv(argv[1], exebuf, sizeof(exebuf)))) {
real = nowl();
argv[1] = exepath;
if ((ws = xvspawn(OnChild, argv + 1, &r)) != -1) {

View file

@ -20,7 +20,7 @@
int main(int argc, char *argv[]) {
int i;
for (i = 1; i < argc; ++i) {
if (touch(argv[i], 0644) == -1) {
if (touch(argv[i], 0666) == -1) {
fprintf(stderr, "ERROR: %s: %s\n", argv[i], strerror(errno));
exit(1);
}

View file

@ -75,7 +75,7 @@ bool isregularfile(const char *);
bool issymlink(const char *);
bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect;
char *commandv(const char *, char[hasatleast PATH_MAX]);
char *commandv(const char *, char *, size_t);
char *get_current_dir_name(void) dontdiscard;
char *getcwd(char *, size_t);
char *realpath(const char *, char *);
@ -120,13 +120,16 @@ int ftruncate(int, int64_t);
int getdents(unsigned, void *, unsigned, long *);
int getdomainname(char *, size_t);
int gethostname(char *, size_t);
int getloadavg(double *, int);
int getpgid(int);
int getpgrp(void) nosideeffect;
int getpid(void);
int gettid(void);
int getppid(void);
int getpriority(int, unsigned);
int getrlimit(int, struct rlimit *);
int getrusage(int, struct rusage *);
int getsid(int) nosideeffect;
int gettid(void);
int kill(int, int);
int killpg(int, int);
int link(const char *, const char *) dontthrow;
@ -165,11 +168,12 @@ int rmdir(const char *);
int sched_getaffinity(int, uint64_t, void *);
int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void);
int seccomp(unsigned, unsigned, void *);
int setegid(uint32_t);
int seteuid(uint32_t);
int setgid(int);
int setpgrp(void);
int setpgid(int, int);
int setpgrp(void);
int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
@ -206,9 +210,9 @@ long ptrace(int, ...);
long telldir(DIR *);
long times(struct tms *);
size_t GetFileSize(const char *);
ssize_t getfiledescriptorsize(int);
ssize_t copy_file_range(int, long *, int, long *, size_t, uint32_t);
ssize_t copyfd(int, int64_t *, int, int64_t *, size_t, uint32_t);
ssize_t getfiledescriptorsize(int);
ssize_t lseek(int, int64_t, unsigned);
ssize_t pread(int, void *, size_t, int64_t);
ssize_t preadv(int, struct iovec *, int, int64_t);
@ -225,14 +229,11 @@ struct dirent *readdir(DIR *);
uint32_t getegid(void) nosideeffect;
uint32_t geteuid(void) nosideeffect;
uint32_t getgid(void) nosideeffect;
uint32_t getpgrp(void) nosideeffect;
uint32_t getsid(int) nosideeffect;
uint32_t getuid(void) nosideeffect;
uint32_t umask(uint32_t);
void rewinddir(DIR *);
void sync(void);
int getloadavg(double *, int);
int seccomp(unsigned, unsigned, void *);
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
int *);

View file

@ -29,7 +29,7 @@
textwindows int sys_chdir_nt(const char *path) {
uint32_t n;
int e, ms, err, len;
char16_t path16[PATH_MAX], var[4];
char16_t path16[PATH_MAX + 1], var[4];
if ((len = __mkntpath(path, path16)) == -1) return -1;
if (!len) return enoent();
if (len && path16[len - 1] != u'\\') {

View file

@ -73,7 +73,9 @@ int close(int fd) {
}
}
}
if (!__vforked) __releasefd(fd);
if (!__vforked) {
__releasefd(fd);
}
}
STRACE("%s(%d) → %d% m", "close", fd, rc);
return rc;

View file

@ -43,15 +43,16 @@ static bool IsComDbgPath(const char *s, size_t n) {
READ64LE(s + n - 8) == READ64LE(".COM.DBG"));
}
static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
static bool AccessCommand(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix,
size_t pathlen) {
size_t suffixlen;
suffixlen = strlen(suffix);
if (pathlen + 1 + namelen + suffixlen + 1 > PATH_MAX) return false;
if (pathlen + 1 + namelen + suffixlen + 1 > pathsz) return false;
if (pathlen && (path[pathlen - 1] != '/' && path[pathlen - 1] != '\\')) {
path[pathlen] =
!IsWindows() ? '/' : memchr(path, '\\', pathlen) ? '\\' : '/';
path[pathlen] = !IsWindows() ? '/'
: memchr(path, '\\', pathlen) ? '\\'
: '/';
pathlen++;
}
memcpy(path + pathlen, name, namelen);
@ -61,7 +62,7 @@ static bool AccessCommand(const char *name, char path[hasatleast PATH_MAX],
return false;
}
static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
static bool SearchPath(const char *name, char *path, size_t pathsz,
size_t namelen, int *err, const char *suffix) {
char sep;
size_t i;
@ -70,11 +71,11 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
sep = IsWindows() && strchr(p, ';') ? ';' : ':';
for (;;) {
for (i = 0; p[i] && p[i] != sep; ++i) {
if (i < PATH_MAX) {
if (i < pathsz) {
path[i] = p[i];
}
}
if (AccessCommand(name, path, namelen, err, suffix, i)) {
if (AccessCommand(name, path, pathsz, namelen, err, suffix, i)) {
return true;
}
if (p[i] == sep) {
@ -86,36 +87,36 @@ static bool SearchPath(const char *name, char path[hasatleast PATH_MAX],
return false;
}
static bool FindCommand(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, const char *suffix,
int *err) {
if (priorityonly &&
(memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
pathbuf[0] = 0;
return AccessCommand(name, pathbuf, namelen, err, suffix, 0);
static bool FindCommand(const char *name, char *pb, size_t pbsz, size_t namelen,
bool pri, const char *suffix, int *err) {
if (pri && (memchr(name, '/', namelen) || memchr(name, '\\', namelen))) {
pb[0] = 0;
return AccessCommand(name, pb, pbsz, namelen, err, suffix, 0);
}
if (IsWindows() && priorityonly) {
return AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, kNtSystemDirectory) - pathbuf) ||
AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, kNtWindowsDirectory) - pathbuf);
if (IsWindows() && pri &&
pbsz > max(strlen(kNtSystemDirectory), strlen(kNtWindowsDirectory))) {
return AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtSystemDirectory) - pb) ||
AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, kNtWindowsDirectory) - pb);
}
return (IsWindows() && AccessCommand(name, pathbuf, namelen, err, suffix,
stpcpy(pathbuf, ".") - pathbuf)) ||
SearchPath(name, pathbuf, namelen, err, suffix);
return (IsWindows() &&
(pbsz > 1 && AccessCommand(name, pb, pbsz, namelen, err, suffix,
stpcpy(pb, ".") - pb))) ||
SearchPath(name, pb, pbsz, namelen, err, suffix);
}
static bool FindVerbatim(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, int *err) {
return FindCommand(name, pathbuf, namelen, priorityonly, "", err);
static bool FindVerbatim(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return FindCommand(name, pb, pbsz, namelen, pri, "", err);
}
static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
size_t namelen, bool priorityonly, int *err) {
static bool FindSuffixed(const char *name, char *pb, size_t pbsz,
size_t namelen, bool pri, int *err) {
return !IsExePath(name, namelen) && !IsComPath(name, namelen) &&
!IsComDbgPath(name, namelen) &&
(FindCommand(name, pathbuf, namelen, priorityonly, ".com", err) ||
FindCommand(name, pathbuf, namelen, priorityonly, ".exe", err));
(FindCommand(name, pb, pbsz, namelen, pri, ".com", err) ||
FindCommand(name, pb, pbsz, namelen, pri, ".exe", err));
}
/**
@ -127,7 +128,7 @@ static bool FindSuffixed(const char *name, char pathbuf[hasatleast PATH_MAX],
* @asyncsignalsafe
* @vforksafe
*/
char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
char *commandv(const char *name, char *pathbuf, size_t pathbufsz) {
int e, f;
char *res;
size_t namelen;
@ -136,25 +137,27 @@ char *commandv(const char *name, char pathbuf[hasatleast PATH_MAX]) {
efault();
} else if (!(namelen = strlen(name))) {
enoent();
} else if (namelen + 1 > PATH_MAX) {
} else if (namelen + 1 > pathbufsz) {
enametoolong();
} else {
e = errno;
f = ENOENT;
if ((IsWindows() && (FindSuffixed(name, pathbuf, namelen, true, &f) ||
FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, false, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f))) ||
(!IsWindows() && (FindVerbatim(name, pathbuf, namelen, true, &f) ||
FindSuffixed(name, pathbuf, namelen, true, &f) ||
FindVerbatim(name, pathbuf, namelen, false, &f) ||
FindSuffixed(name, pathbuf, namelen, false, &f)))) {
if ((IsWindows() &&
(FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f))) ||
(!IsWindows() &&
(FindVerbatim(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, true, &f) ||
FindVerbatim(name, pathbuf, pathbufsz, namelen, false, &f) ||
FindSuffixed(name, pathbuf, pathbufsz, namelen, false, &f)))) {
errno = e;
res = pathbuf;
} else {
errno = f;
}
}
STRACE("commandv(%#s, %p) → %#s% m", name, pathbuf, res);
STRACE("commandv(%#s, %p, %'zu) → %#s% m", name, pathbuf, pathbufsz, res);
return res;
}

View file

@ -37,7 +37,7 @@ static textwindows int sys_copyfile_nt(const char *src, const char *dst,
int flags) {
int64_t fhsrc, fhdst;
struct NtFileTime accessed, modified;
char16_t src16[PATH_MAX], dst16[PATH_MAX];
char16_t src16[PATH_MAX + 1], dst16[PATH_MAX + 1];
if (__mkntpath(src, src16) == -1) return -1;
if (__mkntpath(dst, dst16) == -1) return -1;
if (CopyFile(src16, dst16, !!(flags & COPYFILE_NOCLOBBER))) {

View file

@ -39,8 +39,8 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
char *exe;
char **argv;
va_list va, vb;
char pathbuf[PATH_MAX];
if (!(exe = commandv(prog, pathbuf))) return -1;
char pathbuf[PATH_MAX + 1];
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
va_copy(vb, va);
va_start(va, arg);
for (i = 0; va_arg(va, const char *); ++i) donothing;

View file

@ -33,7 +33,8 @@ int sys_execve(const char *prog, char *const argv[], char *const envp[]) {
shargs = alloca((i + 2) * sizeof(char *));
memcpy(shargs + 2, argv + 1, i * sizeof(char *));
if (IsFreebsd() || IsNetbsd()) {
shargs[0] = firstnonnull(commandv("bash", alloca(PATH_MAX)), _PATH_BSHELL);
shargs[0] = firstnonnull(
commandv("bash", alloca(PATH_MAX + 1), PATH_MAX + 1), _PATH_BSHELL);
} else {
shargs[0] = _PATH_BSHELL;
}

View file

@ -60,7 +60,7 @@ int execve(const char *prog, char *const argv[], char *const envp[]) {
if (i) kprintf(", ");
kprintf("%#s", envp[i]);
}
kprintf("})%n");
kprintf("})\n");
}
#endif
for (i = 3; i < g_fds.n; ++i) {

View file

@ -36,8 +36,8 @@
*/
int execvpe(const char *prog, char *const argv[], char *const *envp) {
char *exe;
char pathbuf[PATH_MAX];
char pathbuf[PATH_MAX + 1];
if (IsAsan() && !__asan_is_valid(prog, 1)) return efault();
if (!(exe = commandv(prog, pathbuf))) return -1;
if (!(exe = commandv(prog, pathbuf, sizeof(pathbuf)))) return -1;
return execve(exe, argv, envp);
}

View file

@ -22,7 +22,7 @@
#include "libc/sysv/errfuns.h"
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
}

View file

@ -24,7 +24,7 @@
textwindows int sys_fchdir_nt(int dirfd) {
uint32_t len;
char16_t dir[PATH_MAX];
char16_t dir[PATH_MAX + 1];
if (!__isfdkind(dirfd, kFdFile)) return ebadf();
len = GetFinalPathNameByHandle(g_fds.p[dirfd].handle, dir, ARRAYLEN(dir),
kNtFileNameNormalized | kNtVolumeNameDos);

View file

@ -23,7 +23,7 @@
textwindows int sys_fchmodat_nt(int dirfd, const char *path, uint32_t mode,
int flags) {
uint32_t attr;
uint16_t path16[PATH_MAX];
uint16_t path16[PATH_MAX + 1];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((attr = GetFileAttributes(path16)) != -1u) {
if (mode & 0200) {

View file

@ -48,7 +48,7 @@ bool fileexists(const char *path) {
bool res;
union metastat st;
struct ZiposUri zipname;
uint16_t path16[PATH_MAX];
uint16_t path16[PATH_MAX + 1];
e = errno;
if (IsAsan() && !__asan_is_valid(path, 1)) {
efault();

View file

@ -29,7 +29,7 @@ textwindows int sys_fstatat_nt(int dirfd, const char *path, struct stat *st,
int flags) {
int rc;
int64_t fh;
uint16_t path16[PATH_MAX];
uint16_t path16[PATH_MAX + 1];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((fh = CreateFile(
path16, kNtFileReadAttributes, 0, 0, kNtOpenExisting,

View file

@ -28,15 +28,22 @@ textwindows char *sys_getcwd_nt(char *buf, size_t size) {
uint64_t w;
wint_t x, y;
uint32_t n, i, j;
char16_t name16[PATH_MAX + 1];
if ((n = GetCurrentDirectory(ARRAYLEN(name16), name16))) {
if (n <= PATH_MAX) {
tprecode16to8(buf, size, name16);
for (j = i = 0; i < n;) {
x = name16[i++] & 0xffff;
char16_t p[PATH_MAX + 1];
if ((n = GetCurrentDirectory(ARRAYLEN(p), p))) {
if (4 + n + 1 <= size && 4 + n + 1 <= ARRAYLEN(p)) {
tprecode16to8(buf, size, p);
j = 0;
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
buf[j++] = '/';
buf[j++] = '/';
buf[j++] = '?';
buf[j++] = '/';
}
for (i = 0; i < n;) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {
if (i < n) {
y = name16[i++] & 0xffff;
y = p[i++] & 0xffff;
x = MergeUtf16(x, y);
} else {
x = 0xfffd;

View file

@ -19,13 +19,19 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/dce.h"
/**
* Returns effective group ID of calling process.
* @return group id
*/
uint32_t getegid(void) {
int rc;
rc = sys_getegid();
if (!IsWindows()) {
rc = sys_getegid();
} else {
rc = getgid();
}
STRACE("%s() → %d% m", "getegid", rc);
return rc;
}

View file

@ -22,10 +22,15 @@
/**
* Returns effective user ID of calling process.
* @return user id
*/
uint32_t geteuid(void) {
int rc;
rc = sys_geteuid();
if (!IsWindows()) {
rc = sys_geteuid();
} else {
rc = getuid();
}
STRACE("%s() → %d% m", "geteuid", rc);
return rc;
}

View file

@ -24,7 +24,7 @@
/**
* Returns process group id of calling process.
*/
uint32_t getpgrp(void) {
int getpgrp(void) {
int rc;
if (!IsWindows()) {
rc = sys_getpgrp();

View file

@ -18,11 +18,14 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/sig.internal.h"
#include "libc/calls/struct/rusage.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/spinlock.h"
#include "libc/nt/accounting.h"
#include "libc/nt/process.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/iocounters.h"
#include "libc/nt/struct/processmemorycounters.h"
#include "libc/nt/thread.h"
#include "libc/str/str.h"
@ -30,22 +33,32 @@
#include "libc/sysv/errfuns.h"
textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
int64_t me, nsignals;
struct NtIoCounters iocount;
struct NtProcessMemoryCountersEx memcount;
struct NtFileTime ftExit, ftUser, ftKernel, ftCreation;
if (!usage) return efault();
if (who == 99) return enosys(); // @see libc/sysv/consts.sh
if (!usage) return 0;
me = GetCurrentProcess();
if (!(who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
&ftCreation, &ftExit, &ftKernel, &ftUser) ||
!GetProcessMemoryInfo(GetCurrentProcess(), &memcount, sizeof(memcount))) {
!GetProcessMemoryInfo(me, &memcount, sizeof(memcount)) ||
!GetProcessIoCounters(me, &iocount)) {
return __winerr();
}
_spinlock(&__sig_lock);
nsignals = __sig_count;
_spunlock(&__sig_lock);
*usage = (struct rusage){
.ru_utime = WindowsDurationToTimeVal(ReadFileTime(ftUser)),
.ru_stime = WindowsDurationToTimeVal(ReadFileTime(ftKernel)),
.ru_maxrss = memcount.PeakWorkingSetSize / 1024,
.ru_majflt = memcount.PageFaultCount,
.ru_inblock = iocount.ReadOperationCount,
.ru_oublock = iocount.WriteOperationCount,
.ru_nsignals = __sig_count,
};
return 0;
}

View file

@ -23,7 +23,7 @@
/**
* Creates session and sets the process group id.
*/
uint32_t getsid(int pid) {
int getsid(int pid) {
int rc;
rc = sys_getsid(pid);
STRACE("%s(%d) → %d% m", "getsid", pid, rc);

View file

@ -88,7 +88,7 @@ int __reservefd(int) hidden;
void __releasefd(int) hidden;
int __ensurefds(int) hidden;
int64_t __getfdhandleactual(int) hidden;
void __printfds(void);
void __printfds(void) hidden;
forceinline bool __isfdopen(int fd) {
return 0 <= fd && fd < g_fds.n && g_fds.p[fd].kind != kFdEmpty;
@ -165,6 +165,7 @@ i32 sys_getppid(void) hidden;
i32 sys_getpriority(i32, u32) hidden;
i32 sys_getrlimit(i32, struct rlimit *) hidden;
i32 sys_getrusage(i32, struct rusage *) hidden;
i32 sys_getsid(int) hidden;
i32 sys_ioctl(i32, u64, ...) hidden;
i32 sys_kill(i32, i32, i32) hidden;
i32 sys_linkat(i32, const char *, i32, const char *, i32) hidden;
@ -191,8 +192,10 @@ i32 sys_setgid(i32) hidden;
i32 sys_setitimer(i32, const struct itimerval *, struct itimerval *) hidden;
i32 sys_setpgid(i32, i32) hidden;
i32 sys_setpriority(i32, u32, i32) hidden;
i32 sys_setregid(u32, u32) hidden;
i32 sys_setresgid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
i32 sys_setreuid(u32, u32) hidden;
i32 sys_setrlimit(i32, const struct rlimit *) hidden;
i32 sys_setsid(void) hidden;
i32 sys_setuid(i32) hidden;
@ -230,7 +233,6 @@ i64 sys_write(i32, const void *, u64) hidden;
u32 sys_getegid(void) hidden;
u32 sys_geteuid(void) hidden;
u32 sys_getgid(void) hidden;
u32 sys_getsid(int) hidden;
u32 sys_gettid(void) hidden;
u32 sys_getuid(void) hidden;
u32 sys_umask(u32) hidden;
@ -337,9 +339,10 @@ bool isregularfile_nt(const char *) hidden;
bool issymlink_nt(const char *) hidden;
bool32 ntsetprivilege(i64, const char16_t *, u32) hidden;
char16_t *CreatePipeName(char16_t *) hidden;
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX - 16]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX - 16], int) hidden;
int __mkntpathat(int, const char *, int, char16_t[PATH_MAX]) hidden;
int __mkntpath(const char *, char16_t[hasatleast PATH_MAX + 1]) hidden;
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX + 1], int) hidden;
int __mkntpathat(int, const char *, int,
char16_t[hasatleast PATH_MAX + 1]) hidden;
int sys_clock_gettime_nt(int, struct timespec *) hidden;
int ntaccesscheck(const char16_t *, u32) paramsnonnull() hidden;
int sys_getsetpriority_nt(int, int, int, int (*)(int));

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/termios.h"
#include "libc/calls/ttydefaults.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/struct/consolescreenbufferinfoex.h"
@ -35,6 +36,23 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
bzero(tio, sizeof(*tio));
tio->c_cflag |= CS8;
tio->c_cc[VINTR] = CTRL('C');
tio->c_cc[VQUIT] = CTRL('\\');
tio->c_cc[VERASE] = CTRL('?');
tio->c_cc[VKILL] = CTRL('U');
tio->c_cc[VEOF] = CTRL('D');
tio->c_cc[VMIN] = CTRL('A');
tio->c_cc[VSTART] = CTRL('Q');
tio->c_cc[VSTOP] = CTRL('S');
tio->c_cc[VSUSP] = CTRL('Z');
tio->c_cc[VREPRINT] = CTRL('R');
tio->c_cc[VDISCARD] = CTRL('O');
tio->c_cc[VWERASE] = CTRL('W');
tio->c_cc[VLNEXT] = CTRL('V');
if (inok) {
if (inmode & kNtEnableLineInput) {
tio->c_lflag |= ICANON;
@ -44,16 +62,21 @@ textwindows int ioctl_tcgets_nt(int ignored, struct termios *tio) {
}
if (inmode & kNtEnableProcessedInput) {
tio->c_lflag |= IEXTEN | ISIG;
if (tio->c_lflag | ECHO) {
tio->c_lflag |= ECHOE;
}
}
}
if (outok) {
if (outmode & kNtEnableProcessedOutput) {
tio->c_oflag |= OPOST;
}
if (!(outmode & kNtDisableNewlineAutoReturn)) {
tio->c_oflag |= ONLCR;
tio->c_oflag |= OPOST | ONLCR;
}
}
return 0;
} else {
return enotty();

View file

@ -17,8 +17,10 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/termios.internal.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/nt/console.h"
#include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/version.h"
@ -29,35 +31,54 @@
textwindows int ioctl_tcsets_nt(int ignored, uint64_t request,
const struct termios *tio) {
int64_t in, out;
bool32 inok, outok;
bool32 ok, inok, outok;
uint32_t inmode, outmode;
inok = GetConsoleMode((in = __getfdhandleactual(0)), &inmode);
outok = GetConsoleMode((out = __getfdhandleactual(1)), &outmode);
if (inok | outok) {
if (inok) {
if (request == TCSETSF) {
FlushConsoleInputBuffer(in);
}
inmode &=
~(kNtEnableLineInput | kNtEnableEchoInput | kNtEnableProcessedInput);
if (tio->c_lflag & ICANON) inmode |= kNtEnableLineInput;
if (tio->c_lflag & ECHO) inmode |= kNtEnableEchoInput;
if (tio->c_lflag & (IEXTEN | ISIG)) inmode |= kNtEnableProcessedInput;
inmode |= kNtEnableWindowInput;
if (tio->c_lflag & ICANON) {
inmode |= kNtEnableLineInput;
}
if (tio->c_lflag & ECHO) {
/*
* kNtEnableEchoInput can be used only if the ENABLE_LINE_INPUT mode
* is also enabled. --Quoth MSDN
*/
inmode |= kNtEnableEchoInput | kNtEnableLineInput;
}
if (tio->c_lflag & (IEXTEN | ISIG)) {
inmode |= kNtEnableProcessedInput;
}
if (NtGetVersion() >= kNtVersionWindows10) {
inmode |= kNtEnableVirtualTerminalInput;
}
SetConsoleMode(in, inmode);
ok = SetConsoleMode(in, inmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", in,
DescribeNtConsoleModeInputFlags(inmode), ok);
}
if (outok) {
outmode |= kNtEnableWrapAtEolOutput;
if (tio->c_oflag & OPOST) outmode |= kNtEnableProcessedOutput;
if (!(tio->c_oflag & ONLCR)) outmode |= kNtDisableNewlineAutoReturn;
outmode &= ~(kNtDisableNewlineAutoReturn);
outmode |= kNtEnableProcessedOutput;
if (!(tio->c_oflag & ONLCR)) {
outmode |= kNtDisableNewlineAutoReturn;
}
if (NtGetVersion() >= kNtVersionWindows10) {
outmode |= kNtEnableVirtualTerminalProcessing;
}
SetConsoleMode(out, outmode);
ok = SetConsoleMode(out, outmode);
NTTRACE("SetConsoleMode(%p, %s) → %hhhd", out,
DescribeNtConsoleModeOutputFlags(outmode), ok);
}
return 0;
} else {
return enotty();

View file

@ -83,11 +83,6 @@ int ioctl_tcsets(int fd, uint64_t request, ...) {
} else {
rc = einval();
}
if (rc != -1) {
if (__nomultics == 0 || __nomultics == 1) {
__nomultics = !(tio->c_oflag & OPOST);
}
}
STRACE("ioctl_tcsets(%d, %p, %p) → %d% m", fd, request, tio, rc);
return rc;
}

View file

@ -28,7 +28,7 @@
bool isdirectory_nt(const char *path) {
int e;
uint32_t x;
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
e = errno;
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {

View file

@ -28,7 +28,7 @@
bool isregularfile_nt(const char *path) {
int e;
uint32_t x;
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
e = errno;
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {

View file

@ -28,7 +28,7 @@
bool issymlink_nt(const char *path) {
int e;
uint32_t x;
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
e = errno;
if (__mkntpath(path, path16) == -1) return -1;
if ((x = GetFileAttributes(path16)) != -1u) {

View file

@ -23,8 +23,8 @@
textwindows int sys_linkat_nt(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
char16_t newpath16[PATH_MAX];
char16_t oldpath16[PATH_MAX];
char16_t newpath16[PATH_MAX + 1];
char16_t oldpath16[PATH_MAX + 1];
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) != -1 &&
__mkntpathat(newdirfd, newpath, 0, newpath16) != -1) {
if (CreateHardLink(newpath16, oldpath16, NULL)) {

View file

@ -36,7 +36,7 @@
* @param path is a UTF-8 string, preferably relative w/ forward slashes
* @param mode can be, for example, 0755
* @return 0 on success or -1 w/ errno
* @error EEXIST, ENOTDIR, ENAMETOOLONG, EACCES
* @error ENAMETOOLONG if >246 characters on NT
* @asyncsignalsafe
* @see makedirs()
*/

View file

@ -18,10 +18,13 @@
*/
#include "libc/calls/internal.h"
#include "libc/nt/files.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
textwindows int sys_mkdirat_nt(int dirfd, const char *path, uint32_t mode) {
int e;
char16_t *p, path16[PATH_MAX];
char16_t *p, path16[PATH_MAX + 1];
/* if (strlen(path) > 248) return enametoolong(); */
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if (CreateDirectory(path16, 0)) return 0;
return __fix_enotdir(-1, path16);

View file

@ -19,6 +19,7 @@
#include "libc/calls/internal.h"
#include "libc/calls/ntmagicpaths.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/oldutf16.internal.h"
#include "libc/str/str.h"
@ -49,7 +50,7 @@ textwindows static const char *FixNtMagicPath(const char *path,
}
textwindows int __mkntpath(const char *path,
char16_t path16[hasatleast PATH_MAX - 16]) {
char16_t path16[hasatleast PATH_MAX + 1]) {
return __mkntpath2(path, path16, -1);
}
@ -67,14 +68,14 @@ textwindows int __mkntpath(const char *path,
* @error ENAMETOOLONG
*/
textwindows int __mkntpath2(const char *path,
char16_t path16[hasatleast PATH_MAX - 16],
char16_t path16[hasatleast PATH_MAX + 1],
int flags) {
/*
* 1. Reserve +1 for NUL-terminator
* 2. Reserve +1 for UTF-16 overflow
* 3. Reserve 2 for SetCurrentDirectory trailing slash requirement
* 4. Reserve 10 for CreateNamedPipe "\\.\pipe\" prefix requirement
* 5. Reserve 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
* 1. Need +1 for NUL-terminator
* 2. Need +1 for UTF-16 overflow
* 3. Need 2 for SetCurrentDirectory trailing slash requirement
* 5. Need 13 for mkdir() i.e. 1+8+3+1, e.g. "\\ffffffff.xxx\0"
* which is an "8.3 filename" from the DOS days
*/
char16_t *p;
const char *q;
@ -83,7 +84,12 @@ textwindows int __mkntpath2(const char *path,
path = FixNtMagicPath(path, flags);
p = path16;
q = path;
z = PATH_MAX - 16;
if (IsSlash(path[0]) && IsSlash(path[1]) && path[2] == '?' &&
IsSlash(path[3])) {
z = MIN(32767, PATH_MAX);
} else {
z = MIN(260, PATH_MAX);
}
if (IsSlash(q[0]) && q[1] == 't' && q[2] == 'm' && q[3] == 'p' &&
(IsSlash(q[4]) || !q[4])) {
m = GetTempPath(z, p);

View file

@ -25,9 +25,9 @@
#include "libc/sysv/errfuns.h"
int __mkntpathat(int dirfd, const char *path, int flags,
char16_t file[PATH_MAX]) {
char16_t dir[PATH_MAX];
char16_t file[hasatleast PATH_MAX + 1]) {
uint32_t dirlen, filelen;
char16_t dir[PATH_MAX + 1];
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
if (!filelen) return enoent();
if (file[0] != u'\\' && dirfd != AT_FDCWD) { /* ProTip: \\?\C:\foo */

View file

@ -20,6 +20,7 @@
#include "libc/calls/sig.internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/errno.h"
#include "libc/limits.h"
#include "libc/macros.internal.h"
#include "libc/nt/errors.h"
#include "libc/nt/nt/time.h"
@ -34,7 +35,7 @@ textwindows noinstrument int sys_nanosleep_nt(const struct timespec *req,
int64_t ms, sec, nsec;
if (__builtin_mul_overflow(req->tv_sec, 1000, &ms) ||
__builtin_add_overflow(ms, req->tv_nsec / 1000000, &ms)) {
ms = -1;
ms = INT64_MAX;
}
if (!ms && (req->tv_sec || req->tv_nsec)) {
ms = 1;

View file

@ -70,7 +70,7 @@ textwindows int ntspawn(
int64_t handle;
size_t blocksize;
struct SpawnBlock *block;
char16_t prog16[PATH_MAX];
char16_t prog16[PATH_MAX + 1];
rc = -1;
block = NULL;
if (__mkntpath(prog, prog16) == -1) return -1;

View file

@ -38,7 +38,7 @@
static textwindows int64_t sys_open_nt_impl(int dirfd, const char *path,
uint32_t flags, int32_t mode) {
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
uint32_t perm, share, disp, attr;
if (__mkntpathat(dirfd, path, flags, path16) == -1) return -1;
if (GetNtOpenFlags(flags, mode, &perm, &share, &disp, &attr) == -1) return -1;

View file

@ -95,7 +95,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout_ms) {
DescribePollFlags(flagbuf[0], sizeof(flagbuf[0]), fds[i].events),
DescribePollFlags(flagbuf[1], sizeof(flagbuf[1]), fds[i].revents));
}
kprintf("%s}, %'zu, %'d) → %d% lm%n", i == 5 ? "..." : "", nfds,
kprintf("%s}, %'zu, %'d) → %d% lm\n", i == 5 ? "..." : "", nfds,
timeout_ms, rc);
}
}

View file

@ -118,7 +118,7 @@ ssize_t preadv(int fd, struct iovec *iov, int iovlen, int64_t off) {
} else {
kprintf(STRACE_PROLOGUE "preadv(%d, [", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d, %'ld) → %'ld% m%n", iovlen, off, rc);
kprintf("], %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
}
#endif

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/spinlock.h"
static const char *__fdkind2str(int x) {
switch (x) {
@ -44,6 +45,7 @@ static const char *__fdkind2str(int x) {
void __printfds(void) {
int i;
_spinlock(&__fds_lock);
for (i = 0; i < g_fds.n; ++i) {
if (!g_fds.p[i].kind) continue;
kprintf("%3d %s", i, __fdkind2str(g_fds.p[i].kind));
@ -53,6 +55,7 @@ void __printfds(void) {
if (g_fds.p[i].handle) kprintf(" handle=%ld", g_fds.p[i].handle);
if (g_fds.p[i].extra) kprintf(" extra=%ld", g_fds.p[i].extra);
if (g_fds.p[i].worker) kprintf(" worker=%p", g_fds.p[i].worker);
kprintf("%n", g_fds.p[i].zombie);
kprintf("\n");
}
_spunlock(&__fds_lock);
}

View file

@ -52,14 +52,21 @@ static textwindows bool GetNtExePath(char exe[SIZE]) {
uint64_t w;
wint_t x, y;
uint32_t i, j;
char16_t path16[PATH_MAX + 1];
path16[0] = 0;
rc = GetModuleFileName(0, path16, ARRAYLEN(path16));
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", path16, rc);
char16_t p[PATH_MAX + 1];
p[0] = 0;
rc = GetModuleFileName(0, p, ARRAYLEN(p));
NTTRACE("GetModuleFileName(0, [%#hs]) → %hhhd", p, rc);
if (!rc) return false;
for (i = j = 0; (x = path16[i++] & 0xffff);) {
j = 0;
if (p[0] != '\\' || p[1] != '\\' || p[2] != '?' || p[3] != '\\') {
exe[j++] = '/';
exe[j++] = '/';
exe[j++] = '?';
exe[j++] = '/';
}
for (i = 0; (x = p[i++] & 0xffff);) {
if (!IsUcs2(x)) {
y = path16[i++] & 0xffff;
y = p[i++] & 0xffff;
x = MergeUtf16(x, y);
}
if (x == '\\') x = '/';

View file

@ -123,7 +123,7 @@ ssize_t pwritev(int fd, const struct iovec *iov, int iovlen, int64_t off) {
} else {
kprintf(STRACE_PROLOGUE "pwritev(%d, ", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf(", %d, %'ld) → %'ld% m%n", iovlen, off, rc);
kprintf(", %d, %'ld) → %'ld% m\n", iovlen, off, rc);
}
}
#endif

View file

@ -27,6 +27,7 @@
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/nt/struct/reparsedatabuffer.h"
#include "libc/str/str.h"
#include "libc/str/tpenc.h"
#include "libc/str/utf16.h"
#include "libc/sysv/errfuns.h"
@ -39,7 +40,7 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
wint_t x, y;
volatile char *memory;
uint32_t i, j, n, mem;
char16_t path16[PATH_MAX], *p;
char16_t path16[PATH_MAX + 1], *p;
struct NtReparseDataBuffer *rdb;
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
mem = 16384;
@ -56,6 +57,12 @@ textwindows ssize_t sys_readlinkat_nt(int dirfd, const char *path, char *buf,
n = rdb->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(char16_t);
p = (char16_t *)((char *)rdb->SymbolicLinkReparseBuffer.PathBuffer +
rdb->SymbolicLinkReparseBuffer.PrintNameOffset);
if (n >= 3 && isalpha(p[0]) && p[1] == ':' && p[2] == '\\') {
buf[j++] = '/';
buf[j++] = '/';
buf[j++] = '?';
buf[j++] = '/';
}
while (i < n) {
x = p[i++] & 0xffff;
if (!IsUcs2(x)) {

View file

@ -72,7 +72,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
} else {
kprintf(STRACE_PROLOGUE "readv(%d, [", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf("], %d) → %'ld% m%n", iovlen, rc);
kprintf("], %d) → %'ld% m\n", iovlen, rc);
}
}
#endif

View file

@ -22,8 +22,8 @@
textwindows int sys_renameat_nt(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) {
char16_t oldpath16[PATH_MAX];
char16_t newpath16[PATH_MAX];
char16_t oldpath16[PATH_MAX + 1];
char16_t newpath16[PATH_MAX + 1];
if (__mkntpathat(olddirfd, oldpath, 0, oldpath16) == -1 ||
__mkntpathat(newdirfd, newpath, 0, newpath16) == -1) {
return -1;

View file

@ -22,9 +22,6 @@
/**
* Sets effective group ID.
*/
int setegid(unsigned egid) {
int rc;
rc = setregid(-1, egid);
STRACE("%s(%u) → %d% m", "setegid", egid, rc);
return rc;
int setegid(uint32_t egid) {
return setregid(-1, egid);
}

View file

@ -22,9 +22,6 @@
/**
* Sets effective user ID.
*/
int seteuid(unsigned euid) {
int rc;
rc = setreuid(-1, euid);
STRACE("%s(%u) → %d% m", "seteuid", euid, rc);
return rc;
int seteuid(uint32_t euid) {
return setregid(euid, -1);
}

View file

@ -21,12 +21,16 @@
#include "libc/calls/strace.internal.h"
/**
* Sets effective group id of current process.
* Sets group id of current process.
* @return 0 on success or -1 w/ errno
*/
int setgid(int gid) {
int rc;
rc = sys_setgid(gid);
STRACE("%s(%d) → %d% m", "setgid", gid);
if (IsWindows() && gid == getgid()) {
rc = 0;
} else {
rc = sys_setgid(gid);
}
STRACE("setgid(%d) → %d% m", gid, rc);
return rc;
}

35
libc/calls/setregid.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real and/or effective group ids.
*
* @param rgid is real group id or -1 to leave it unchanged
* @param egid is effective group id or -1 to leave it unchanged
* @return 0 on success or -1 w/ errno
*/
int setregid(uint32_t rgid, uint32_t egid) {
int rc;
rc = sys_setregid(rgid, egid);
STRACE("setregid(%d, %d) → %d% m", rgid, egid, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real, effective, and "saved" group ids.
@ -25,9 +26,17 @@
* @param real sets real group id or -1 to do nothing
* @param effective sets effective group id or -1 to do nothing
* @param saved sets saved group id or -1 to do nothing
* @see setregid(), getauxval(AT_SECURE)
* @see setresuid(), getauxval(AT_SECURE)
* @raise ENOSYS on Windows NT
*/
int setresgid(uint32_t real, uint32_t effective, uint32_t saved) {
if (saved == -1) return setregid(real, effective);
return sys_setresgid(real, effective, saved);
int rc;
if (saved != -1) {
rc = sys_setresgid(real, effective, saved);
} else {
// polyfill xnu and netbsd
rc = sys_setregid(real, effective);
}
STRACE("setresgid(%d, %d, %d) → %d% m", real, effective, saved, rc);
return rc;
}

View file

@ -18,6 +18,7 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real, effective, and "saved" user ids.
@ -25,9 +26,17 @@
* @param real sets real user id or -1 to do nothing
* @param effective sets effective user id or -1 to do nothing
* @param saved sets saved user id or -1 to do nothing
* @see setreuid(), getauxval(AT_SECURE)
* @see setresgid(), getauxval(AT_SECURE)
* @raise ENOSYS on Windows NT
*/
int setresuid(uint32_t real, uint32_t effective, uint32_t saved) {
if (saved == -1) return setreuid(real, effective);
return sys_setresuid(real, effective, saved);
int rc;
if (saved != -1) {
rc = sys_setresuid(real, effective, saved);
} else {
// polyfill xnu and netbsd
rc = sys_setreuid(real, effective);
}
STRACE("setresuid(%d, %d, %d) → %d% m", real, effective, saved, rc);
return rc;
}

35
libc/calls/setreuid.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
/**
* Sets real and/or effective user ids.
*
* @param ruid is real user id or -1 to leave it unchanged
* @param euid is effective user id or -1 to leave it unchanged
* @return 0 on success or -1 w/ errno
*/
int setreuid(uint32_t ruid, uint32_t euid) {
int rc;
rc = sys_setreuid(ruid, euid);
STRACE("setreuid(%d, %d) → %d% m", ruid, euid, rc);
return rc;
}

View file

@ -21,12 +21,16 @@
#include "libc/calls/strace.internal.h"
/**
* Sets effective group id of current process.
* Sets user id of current process.
* @return 0 on success or -1 w/ errno
*/
int setuid(int uid) {
int rc;
rc = sys_setuid(uid);
STRACE("%s(%d) → %d% m", "setuid", uid);
if (IsWindows() && uid == getuid()) {
rc = 0;
} else {
rc = sys_setuid(uid);
}
STRACE("setuid(%d) → %d% m", uid, rc);
return rc;
}

View file

@ -24,6 +24,7 @@ struct Signals {
};
extern struct Signals __sig; // TODO(jart): Need TLS
extern long __sig_count;
bool __sig_check(bool) hidden;
bool __sig_handle(bool, int, int, ucontext_t *) hidden;

View file

@ -222,6 +222,7 @@ textwindows int __sig_add(int sig, int si_code) {
if (1 <= sig && sig <= NSIG) {
STRACE("enqueuing %G", sig);
_spinlock(&__sig_lock);
++__sig_count;
if ((mem = __sig_alloc())) {
mem->sig = sig;
mem->si_code = si_code;

21
libc/calls/sigcount.c Normal file
View file

@ -0,0 +1,21 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/sig.internal.h"
long __sig_count;

View file

@ -5,8 +5,8 @@
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#define _KERNTRACE 1 /* not configurable w/ flag yet */
#define _POLLTRACE 1 /* not configurable w/ flag yet */
#define _KERNTRACE 0 /* not configurable w/ flag yet */
#define _POLLTRACE 0 /* not configurable w/ flag yet */
#define _DATATRACE 1 /* not configurable w/ flag yet */
#define _NTTRACE 1 /* not configurable w/ flag yet */
@ -19,7 +19,7 @@ COSMOPOLITAN_C_START_
#define STRACE(FMT, ...) \
do { \
if (__strace > 0) { \
__stracef(STRACE_PROLOGUE FMT "%n", ##__VA_ARGS__); \
__stracef(STRACE_PROLOGUE FMT "\n", ##__VA_ARGS__); \
} \
} while (0)
#else

View file

@ -53,8 +53,8 @@ textwindows int sys_symlinkat_nt(const char *target, int newdirfd,
const char *linkpath) {
int targetlen;
uint32_t attrs, flags;
char16_t target16[PATH_MAX];
char16_t linkpath16[PATH_MAX];
char16_t target16[PATH_MAX + 1];
char16_t linkpath16[PATH_MAX + 1];
// convert the paths
if (__mkntpathat(newdirfd, linkpath, 0, linkpath16) == -1) return -1;

View file

@ -28,7 +28,7 @@ textwindows int sys_truncate_nt(const char *path, uint64_t length) {
int rc;
bool32 ok;
int64_t fh;
uint16_t path16[PATH_MAX];
uint16_t path16[PATH_MAX + 1];
if (__mkntpath(path, path16) == -1) return -1;
if ((fh = CreateFile(path16, kNtGenericWrite, kNtFileShareRead, NULL,
kNtOpenExisting, kNtFileAttributeNormal, 0)) != -1) {

View file

@ -19,7 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/log/log.h"
static char ttyname_buf[PATH_MAX];
static char ttyname_buf[PATH_MAX + 1];
/**
* Returns name of terminal.

View file

@ -63,7 +63,7 @@ static int ttyname_freebsd(int fd, char *buf, size_t size) {
static int ttyname_linux(int fd, char *buf, size_t size) {
struct stat st1, st2;
if (!isatty(fd)) return errno;
char name[PATH_MAX];
char name[PATH_MAX + 1];
FormatInt32(stpcpy(name, "/proc/self/fd/"), fd);
ssize_t got;
got = readlink(name, buf, size);

View file

@ -39,7 +39,8 @@
* from failing for no reason at all. For example a unit test that
* repeatedly opens and unlinks the same filename.
*/
static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX], int n) {
static textwindows int SyncDirectory(int df, char16_t path[PATH_MAX + 1],
int n) {
int rc;
int64_t fh;
char16_t *p;
@ -128,7 +129,7 @@ static textwindows int sys_unlink_nt(const char16_t *path) {
textwindows int sys_unlinkat_nt(int dirfd, const char *path, int flags) {
int n, rc;
char16_t path16[PATH_MAX];
char16_t path16[PATH_MAX + 1];
if ((n = __mkntpathat(dirfd, path, 0, path16)) == -1) {
rc = -1;
} else if (flags & AT_REMOVEDIR) {

View file

@ -35,7 +35,7 @@ textwindows int sys_utimensat_nt(int dirfd, const char *path,
const struct timespec ts[2], int flags) {
int i, rc;
int64_t fh;
uint16_t path16[PATH_MAX];
uint16_t path16[PATH_MAX + 1];
struct NtFileTime ft[2], *ftp[2];
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
if ((fh = CreateFile(path16, kNtFileWriteAttributes, kNtFileShareRead, NULL,

View file

@ -95,7 +95,11 @@ static textwindows int sys_wait4_nt_impl(int pid, int *opt_out_wstatus,
return 0;
}
} else {
i = WaitForMultipleObjects(count, handles, false, -1);
i = WaitForMultipleObjects(count, handles, false,
__SIG_POLLING_INTERVAL_MS);
if (i == kNtWaitTimeout) {
continue;
}
}
if (i == kNtWaitFailed) {
STRACE("%s failed %u", "WaitForMultipleObjects", GetLastError());

View file

@ -79,7 +79,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
} else {
kprintf(STRACE_PROLOGUE "writev(%d, ", fd);
__strace_iov(iov, iovlen, rc != -1 ? rc : 0);
kprintf(", %d) → %'ld% m%n", iovlen, rc);
kprintf(", %d) → %'ld% m\n", iovlen, rc);
}
}
#endif

View file

@ -37,7 +37,7 @@ static struct HostsTxtInitialStaticMemory {
} g_hoststxt_init;
static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
uint32_t size) {
uint32_t size) {
const char *const kWinHostsPath = "\\drivers\\etc\\hosts";
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
if (len && len + strlen(kWinHostsPath) + 1 < size) {
@ -57,7 +57,7 @@ static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
const struct HostsTxt *GetHostsTxt(void) {
FILE *f;
const char *path;
char pathbuf[PATH_MAX];
char pathbuf[PATH_MAX + 1];
struct HostsTxtInitialStaticMemory *init;
init = &g_hoststxt_init;
if (!g_hoststxt) {

View file

@ -48,10 +48,10 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found, result;
char pathbuf[PATH_MAX + 1];
char *name, *number, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";

View file

@ -52,10 +52,10 @@ int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found;
size_t linesize;
const char *path;
char pathbuf[PATH_MAX + 1];
char *name, *number, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";

View file

@ -53,10 +53,10 @@ int LookupServicesByName(const char *servname, char *servproto,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found, result;
char pathbuf[PATH_MAX + 1];
char *name, *port, *proto, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/services";

View file

@ -59,7 +59,7 @@ int LookupServicesByPort(const int servport, char *servproto,
const char *filepath) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
char pathbuf[PATH_MAX + 1];
const char *path;
size_t linesize;
int found;

View file

@ -18,6 +18,11 @@
*/
#include "libc/fmt/conv.h"
int(abs)(int x) {
/**
* Returns absolute value of 32-bit integer.
* @note `labs(LONG_MIN)` returns `LONG_MIN` unless `-ftrapv`
* @note consider ABS() to avoid narrowing
*/
int abs(int x) {
return 0 < x ? x : -x;
}

View file

@ -368,9 +368,6 @@ hidden int __fmt(void *fn, void *arg, const char *format, va_list va) {
}
break;
case 'n':
// nonstandard %n specifier
// used to print newlines that work in raw terminal modes
if (__nomultics) __FMT_PUT('\r');
__FMT_PUT('\n');
break;
case 'F':

View file

@ -26,10 +26,6 @@ int sscanf(const char *, const char *, ...) scanfesque(2);
int vsscanf(const char *, const char *, va_list);
int vcscanf(int (*)(void *), int (*)(int, void *), void *, const char *,
va_list);
int strerror_r(int, char *, size_t) dontthrow nocallback;
int strerror_wr(int, uint32_t, char *, size_t) dontthrow nocallback;
const char *strerror_short(int) nosideeffect;
const char *strerror_long(int) nosideeffect;
int __fmt(void *, void *, const char *, va_list) hidden;
char *itoa(int, char *, int) compatfn;
char *fcvt(double, int, int *, int *);

View file

@ -19,8 +19,8 @@
#include "libc/macros.internal.h"
.macro .e e s
.long \e - kErrorNamesLong
.long 1f - kErrorNamesLong
.long \e - kErrnoDocs
.long 1f - kErrnoDocs
.rodata.str1.1
1: .asciz "\s"
.previous
@ -29,7 +29,7 @@
.section .rodata
.align 4
.underrun
kErrorNamesLong:
kErrnoDocs:
.e EINVAL,"Invalid argument"
.e ENOSYS,"Function not implemented"
.e EPERM,"Operation not permitted"
@ -115,6 +115,6 @@ kErrorNamesLong:
.e ENOTRECOVERABLE,"State not recoverable"
.e ENONET,"Machine is not on the network"
.e ERESTART,"Interrupted system call should be restarted"
.long 0
.endobj kErrorNamesLong,globl,hidden
.long -123
.endobj kErrnoDocs,globl,hidden
.overrun

View file

@ -19,8 +19,8 @@
#include "libc/macros.internal.h"
.macro .e e
.long \e - kErrorNames
.long 1f - kErrorNames
.long \e - kErrnoNames
.long 1f - kErrnoNames
.rodata.str1.1
1: .string "\e"
.previous
@ -29,7 +29,7 @@
.section .rodata
.align 4
.underrun
kErrorNames:
kErrnoNames:
.e EINVAL
.e ENOSYS
.e EPERM
@ -116,6 +116,6 @@ kErrorNames:
.e ENONET
.e ERESTART
.e ENODATA
.long 0
.endobj kErrorNames,globl,hidden
.long -123
.endobj kErrnoNames,globl,hidden
.overrun

View file

@ -1,16 +0,0 @@
#ifndef COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
#define COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct ErrorName {
int x, s;
};
extern const struct ErrorName kStrSignal[];
extern const struct ErrorName kErrorNames[];
extern const struct ErrorName kErrorNamesLong[];
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_FMT_KERRORNAMES_INTERNAL_H_ */

View file

@ -17,8 +17,12 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
long(labs)(long x) {
return ABS(x);
/**
* Returns absolute value of long integer.
* @note `labs(LONG_MIN)` returns `LONG_MIN` unless `-ftrapv`
* @note consider ABS() to avoid narrowing
*/
long labs(long x) {
return 0 < x ? x : -x;
}

View file

@ -17,8 +17,12 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/macros.internal.h"
long long(llabs)(long long x) {
return ABS(x);
/**
* Returns absolute value of long long integer.
* @note `llabs(LONG_LONG_MIN)` returns `LONG_LONG_MIN` unless `-ftrapv`
* @note consider ABS() to avoid narrowing
*/
long long llabs(long long x) {
return 0 < x ? x : -x;
}

View file

@ -0,0 +1,23 @@
#ifndef COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_
#define COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct MagnumStr {
int x, s;
};
extern const struct MagnumStr kErrnoDocs[];
extern const struct MagnumStr kErrnoNames[];
extern const struct MagnumStr kIpOptnames[];
extern const struct MagnumStr kSignalNames[];
extern const struct MagnumStr kSockOptnames[];
extern const struct MagnumStr kTcpOptnames[];
const char *DescribeSockLevel(int);
const char *DescribeSockOptname(int, int);
const char *GetMagnumStr(const struct MagnumStr *, int);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_FMT_MAGNUMSTRS_H_ */

View file

@ -17,23 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/fmt/kerrornames.internal.h"
#include "libc/fmt/magnumstrs.internal.h"
/**
* Converts errno value to descriptive sentence.
* @return non-null rodata string or null if not found
*/
privileged const char *strerror_long(int x) {
/* kprintf() weakly depends on this function */
int i;
const char *strerdoc(int x) {
if (x) {
for (i = 0; kErrorNamesLong[i].x; ++i) {
if (x ==
*(const long *)((uintptr_t)kErrorNamesLong + kErrorNamesLong[i].x)) {
return (const char *)((uintptr_t)kErrorNamesLong +
kErrorNamesLong[i].s);
}
}
return GetMagnumStr(kErrnoDocs, x);
} else {
return 0;
}
return 0;
}

View file

@ -16,22 +16,17 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/fmt.h"
#include "libc/fmt/kerrornames.internal.h"
#include "libc/fmt/magnumstrs.internal.h"
#include "libc/str/str.h"
/**
* Converts errno value to symbolic name.
* @return non-null rodata string or null if not found
*/
privileged const char *strerror_short(int x) {
/* kprintf() weakly depends on this function */
int i;
const char *strerrno(int x) {
if (x) {
for (i = 0; kErrorNames[i].x; ++i) {
if (x == *(const int *)((uintptr_t)kErrorNames + kErrorNames[i].x)) {
return (const char *)((uintptr_t)kErrorNames + kErrorNames[i].s);
}
}
return GetMagnumStr(kErrnoNames, x);
} else {
return 0;
}
return 0;
}

View file

@ -23,9 +23,9 @@
* Converts errno value to string non-reentrantly.
* @see strerror_r()
*/
noasan char *strerror(int err) {
char *strerror(int err) {
if (IsTiny()) {
return firstnonnull(strerror_short(err), "EUNKNOWN");
return firstnonnull(strerrno(err), "EUNKNOWN");
} else {
_Alignas(1) static char buf[512];
strerror_r(err, buf, sizeof(buf));

View file

@ -25,6 +25,6 @@
* @param err is error number or zero if unknown
* @return 0 on success, or error code
*/
privileged int strerror_r(int err, char *buf, size_t size) {
int strerror_r(int err, char *buf, size_t size) {
return strerror_wr(err, GetLastError(), buf, size);
}

View file

@ -32,13 +32,13 @@
* @param err is error number or zero if unknown
* @return 0 on success, or error code
*/
privileged int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
int strerror_wr(int err, uint32_t winerr, char *buf, size_t size) {
/* kprintf() weakly depends on this function */
int c, n;
char16_t winmsg[256];
const char *sym, *msg;
sym = firstnonnull(strerror_short(err), "EUNKNOWN");
msg = firstnonnull(strerror_long(err), "No error information");
sym = firstnonnull(strerrno(err), "EUNKNOWN");
msg = firstnonnull(strerdoc(err), "No error information");
if (IsTiny()) {
if (!sym) sym = "EUNKNOWN";
for (; (c = *sym++); --size)

View file

@ -71,7 +71,7 @@
#define CACHELINE 0x40 /* nexgen32e */
#define CHAR_BIT 8 /* b/c von neumann */
#define ARG_MAX 0x8000 /* b/c windows */
#define PATH_MAX 248 /* b/c win32 apis limit ~248..260 */
#define PATH_MAX 512 /* b/c bloat */
#define NAME_MAX 63 /* b/c dns */
#define CHILD_MAX 25 /* only if malloc isn't linked */
#define OPEN_MAX 16 /* only if malloc isn't linked */

View file

@ -59,7 +59,7 @@ STATIC_YOINK("_init_asan");
#define ASAN_MORGUE_ITEMS 512
#define ASAN_MORGUE_THRESHOLD 65536 // morgue memory O(ITEMS*THRESHOLD)
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
#define ASAN_TRACE_ITEMS 16 // backtrace limit on malloc origin
/**
* @fileoverview Cosmopolitan Address Sanitizer Runtime.
@ -102,7 +102,7 @@ STATIC_YOINK("_init_asan");
#define REQUIRE(FUNC) \
do { \
if (!weaken(FUNC)) { \
kprintf("error: asan needs %s%n", #FUNC); \
kprintf("error: asan needs %s\n", #FUNC); \
__asan_die()(); \
__asan_unreachable(); \
} \
@ -179,8 +179,7 @@ static uint64_t __asan_roundup2pow(uint64_t x) {
static char *__asan_utf8cpy(char *p, unsigned c) {
uint64_t z;
z = tpenc(c);
do
*p++ = z;
do *p++ = z;
while ((z >>= 8));
return p;
}
@ -322,9 +321,9 @@ static char *__asan_hexcpy(char *p, uint64_t x, uint8_t k) {
}
static void __asan_exit(void) {
kprintf("your asan runtime needs%n"
"\tSTATIC_YOINK(\"__die\");%n"
"in order to show you backtraces%n");
kprintf("your asan runtime needs\n"
"\tSTATIC_YOINK(\"__die\");\n"
"in order to show you backtraces\n");
__restorewintty();
_Exit(99);
}
@ -373,6 +372,7 @@ void __asan_unpoison(long p, long n) {
}
static bool __asan_is_mapped(int x) {
// xxx: we can't lock because no reentrant locks yet
int i;
struct MemoryIntervals *m;
m = weaken(_mmi);
@ -609,7 +609,7 @@ const char *__asan_describe_access_poison(signed char kind) {
dontdiscard static __asan_die_f *__asan_report_invalid_pointer(
const void *addr) {
kprintf("%n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p%n",
kprintf("\n\e[J\e[1;31masan error\e[0m: this corruption at %p shadow %p\n",
addr, SHADOW(addr));
return __asan_die();
}
@ -629,7 +629,6 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
if (a <= (intptr_t)addr && (intptr_t)addr <= b) {
p = __stpcpy(p, " ←address");
}
if (__nomultics) *p++ = '\r';
*p++ = '\n';
}
return p;
@ -638,7 +637,7 @@ static char *__asan_format_section(char *p, const void *p1, const void *p2,
static void __asan_report_memory_origin_image(intptr_t a, int z) {
unsigned l, m, r, n, k;
struct SymbolTable *st;
kprintf("%nthe memory belongs to image symbols%n");
kprintf("\nthe memory belongs to image symbols\n");
if (weaken(GetSymbolTable)) {
if ((st = weaken(GetSymbolTable)())) {
l = 0;
@ -656,7 +655,7 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
if ((st->symbols[l].x <= k && k <= st->symbols[l].y) ||
(st->symbols[l].x <= k + z && k + z <= st->symbols[l].y) ||
(k < st->symbols[l].x && st->symbols[l].y < k + z)) {
kprintf("\t%s [%#x,%#x] size %'d%n", st->name_base + st->names[l],
kprintf("\t%s [%#x,%#x] size %'d\n", st->name_base + st->names[l],
st->addr_base + st->symbols[l].x,
st->addr_base + st->symbols[l].y,
st->symbols[l].y - st->symbols[l].x + 1);
@ -665,10 +664,10 @@ static void __asan_report_memory_origin_image(intptr_t a, int z) {
}
}
} else {
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG%n");
kprintf("\tunknown please supply .com.dbg symbols or set COMDBG\n");
}
} else {
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");%n");
kprintf("\tunknown please STATIC_YOINK(\"GetSymbolTable\");\n");
}
}
@ -686,13 +685,13 @@ static noasan void OnMemory(void *x, void *y, size_t n, void *a) {
static void __asan_report_memory_origin_heap(const unsigned char *a, int z) {
struct ReportOriginHeap t;
kprintf("%nthe memory was allocated by%n");
kprintf("\nthe memory was allocated by\n");
if (weaken(malloc_inspect_all)) {
t.a = a;
t.z = z;
weaken(malloc_inspect_all)(OnMemory, &t);
} else {
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");%n");
kprintf("\tunknown please STATIC_YOINK(\"malloc_inspect_all\");\n");
}
}
@ -737,7 +736,7 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
struct MemoryIntervals *m;
++g_ftrace;
p = __fatalbuf;
kprintf("%n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p%n%s%n",
kprintf("\n\e[J\e[1;31masan error\e[0m: %s %d-byte %s at %p shadow %p\n%s\n",
__asan_describe_access_poison(kind), size, message, addr,
SHADOW(addr), __argv[0]);
if (0 < size && size < 80) {
@ -753,7 +752,6 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
*p++ = ' ';
}
}
if (__nomultics) *p++ = '\r';
*p++ = '\n';
for (c = i = 0; i < 80; ++i) {
if (!(t = __asan_check(base + i, 1).kind)) {
@ -771,7 +769,6 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
}
}
p = __stpcpy(p, "\e[39m");
if (__nomultics) *p++ = '\r';
*p++ = '\n';
for (i = 0; (intptr_t)(base + i) & 7; ++i) *p++ = ' ';
for (; i + 8 <= 80; i += 8) {
@ -788,19 +785,18 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
}
}
for (; i < 80; ++i) *p++ = ' ';
if (__nomultics) *p++ = '\r';
*p++ = '\n';
for (i = 0; i < 80; ++i) {
p = __asan_utf8cpy(p, __asan_exists(base + i)
? kCp437[((unsigned char *)base)[i]]
: L'');
}
if (__nomultics) *p++ = '\r';
*p++ = '\n';
}
p = __asan_format_section(p, _base, _etext, ".text", addr);
p = __asan_format_section(p, _etext, _edata, ".data", addr);
p = __asan_format_section(p, _end, _edata, ".bss", addr);
// xxx: we can't lock because no reentrant locks yet
for (m = weaken(_mmi), i = 0; i < m->i; ++i) {
x = m->p[i].x;
y = m->p[i].y;
@ -809,13 +805,12 @@ dontdiscard static __asan_die_f *__asan_report(const void *addr, int size,
if (x <= z && z <= y) p = __stpcpy(p, " ←address");
z = (((intptr_t)addr >> 3) + 0x7fff8000) >> 16;
if (x <= z && z <= y) p = __stpcpy(p, " ←shadow");
if (__nomultics) *p++ = '\r';
*p++ = '\n';
}
*p = 0;
kprintf("%s", __fatalbuf);
__asan_report_memory_origin(addr, size, kind);
kprintf("%nthe crash was caused by%n");
kprintf("\nthe crash was caused by\n");
--g_ftrace;
return __asan_die();
}
@ -924,8 +919,7 @@ static void __asan_trace(struct AsanTrace *bt, const struct StackFrame *bp) {
if (!__asan_checka(SHADOW(bp), sizeof(*bp) >> 3).kind) {
addr = bp->addr;
if (addr == weakaddr("__gc") && weakaddr("__gc")) {
do
--gi;
do --gi;
while ((addr = garbage->p[gi].ret) == weakaddr("__gc"));
}
bt->p[i] = addr;
@ -1018,12 +1012,12 @@ int __asan_print_trace(void *p) {
kprintf(" bad cookie");
return -1;
}
kprintf("%n%p %,lu bytes [asan]", (char *)p, n);
kprintf("\n%p %,lu bytes [asan]", (char *)p, n);
if (!__asan_is_mapped((((intptr_t)p >> 3) + 0x7fff8000) >> 16)) {
kprintf(" (shadow not mapped?!)");
}
for (i = 0; i < ARRAYLEN(e->bt.p) && e->bt.p[i]; ++i) {
kprintf("%n%*lx %s", 12, e->bt.p[i],
kprintf("\n%*lx %s", 12, e->bt.p[i],
weaken(__get_symbol_by_addr)
? weaken(__get_symbol_by_addr)(e->bt.p[i])
: "please STATIC_YOINK(\"__get_symbol_by_addr\")");
@ -1203,7 +1197,7 @@ void __asan_evil(uint8_t *addr, int size, const char *s1, const char *s2) {
struct AsanTrace tr;
__asan_rawtrace(&tr, __builtin_frame_address(0));
kprintf(
"WARNING: ASAN error during %s bad %d byte %s at %x bt %x %x %x %x %x%n",
"WARNING: ASAN error during %s bad %d byte %s at %x bt %x %x %x %x %x\n",
s1, size, s2, addr, tr.p[0], tr.p[1], tr.p[2], tr.p[3], tr.p[4], tr.p[5]);
}
@ -1281,6 +1275,7 @@ void __asan_install_malloc_hooks(void) {
}
void __asan_map_shadow(uintptr_t p, size_t n) {
// assume _mmi.lock is held
void *addr;
int i, a, b;
size_t size;
@ -1311,7 +1306,7 @@ void __asan_map_shadow(uintptr_t p, size_t n) {
m, a, a + i - 1, sm.maphandle, PROT_READ | PROT_WRITE,
MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, false, false, 0,
size) == -1) {
kprintf("error: could not map asan shadow memory%n");
kprintf("error: could not map asan shadow memory\n");
__asan_die()();
__asan_unreachable();
}

View file

@ -35,12 +35,12 @@ relegated wontreturn void __assert_fail(const char *expr, const char *file,
static bool noreentry;
__strace = 0;
g_ftrace = 0;
kprintf("%s:%d: assert(%s) failed%n", file, line, expr);
kprintf("%s:%d: assert(%s) failed\n", file, line, expr);
if (_lockcmpxchg(&noreentry, false, true)) {
if (weaken(__die)) {
weaken(__die)();
} else {
kprintf("can't backtrace b/c `__die` not linked%n");
kprintf("can't backtrace b/c `__die` not linked\n");
}
rc = 23;
} else {

View file

@ -26,7 +26,7 @@
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
noasan static dontinline antiquity void bzero_sse(char *p, size_t n) {
static dontinline antiquity void bzero_sse(char *p, size_t n) {
xmm_t v = {0};
if (IsAsan()) __asan_verify(p, n);
if (n <= 32) {
@ -43,7 +43,7 @@ noasan static dontinline antiquity void bzero_sse(char *p, size_t n) {
}
}
noasan microarchitecture("avx") static void bzero_avx(char *p, size_t n) {
microarchitecture("avx") static void bzero_avx(char *p, size_t n) {
xmm_t v = {0};
if (IsAsan()) __asan_verify(p, n);
if (n <= 32) {

View file

@ -0,0 +1,36 @@
/*-*- 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/internal.h"
#include "libc/calls/strace.internal.h"
#include "libc/nt/accounting.h"
#include "libc/nt/thunk/msabi.h"
__msabi extern typeof(GetExitCodeProcess) *const __imp_GetExitCodeProcess;
/**
* Obtains exit code for process.
* @note this wrapper takes care of ABI, STRACE(), and __winerr()
*/
textwindows int32_t GetExitCodeProcess(int64_t hProcess, uint32_t *lpExitCode) {
int32_t rc;
rc = __imp_GetExitCodeProcess(hProcess, lpExitCode);
if (!rc) __winerr();
NTTRACE("GetExitCodeProcess(%ld, [%u]) → %u% m", hProcess, *lpExitCode, rc);
return rc;
}

View 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 2022 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/magnumstrs.internal.h"
const char *GetMagnumStr(const struct MagnumStr *ms, int x) {
int i;
for (i = 0; ms[i].x != -123; ++i) {
if (x == *(const int *)((uintptr_t)ms + ms[i].x)) {
return (const char *)((uintptr_t)ms + ms[i].s);
}
}
return 0;
}

View file

@ -89,9 +89,12 @@ o/$(MODE)/libc/intrin/flushfilebuffers.greg.o \
o/$(MODE)/libc/intrin/terminateprocess.greg.o \
o/$(MODE)/libc/intrin/describemapflags.greg.o \
o/$(MODE)/libc/intrin/getfileattributes.greg.o \
o/$(MODE)/libc/intrin/getexitcodeprocess.greg.o \
o/$(MODE)/libc/intrin/waitforsingleobject.greg.o \
o/$(MODE)/libc/intrin/setcurrentdirectory.greg.o \
o/$(MODE)/libc/intrin/mapviewoffileexnuma.greg.o \
o/$(MODE)/libc/intrin/createfilemappingnuma.greg.o \
o/$(MODE)/libc/intrin/waitformultipleobjects.greg.o \
o/$(MODE)/libc/intrin/generateconsolectrlevent.greg.o \
o/$(MODE)/libc/intrin/kstarttsc.o \
o/$(MODE)/libc/intrin/nomultics.o \

View file

@ -114,7 +114,7 @@ kDos2Errno:
.e kNtErrorCrc,EACCES
.e kNtErrorDirNotEmpty,ENOTEMPTY
.e kNtErrorDupName,EADDRINUSE
.e kNtErrorFilenameExcedRange,ENOENT
.e kNtErrorFilenameExcedRange,ENAMETOOLONG
.e kNtErrorGenFailure,EACCES
.e kNtErrorGracefulDisconnect,EPIPE
.e kNtErrorHostDown,EHOSTUNREACH

View file

@ -32,6 +32,7 @@
#include "libc/intrin/nomultics.internal.h"
#include "libc/intrin/spinlock.h"
#include "libc/limits.h"
#include "libc/log/internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
#include "libc/nexgen32e/uart.internal.h"
@ -174,6 +175,7 @@ privileged static inline bool kismemtrackhosed(void) {
}
privileged static bool kismapped(int x) {
// xxx: we can't lock because no reentrant locks yet
size_t m, r, l = 0;
if (!weaken(_mmi)) return true;
if (kismemtrackhosed()) return false;
@ -450,8 +452,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
i = 0;
m = (1 << base) - 1;
if (hash && x) sign = hash;
do
z[i++ & 127] = abet[x & m];
do z[i++ & 127] = abet[x & m];
while ((x >>= base) || (pdot && i < prec));
goto EmitNumber;
@ -556,11 +557,6 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
case 'n':
// nonstandard %n specifier
// used to print newlines that work in raw terminal modes
if (__nomultics) {
if (p < e) *p = '\r';
++p;
}
if (p < e) *p = '\n';
++p;
break;
@ -569,7 +565,7 @@ privileged static size_t kformat(char *b, size_t n, const char *fmt, va_list va,
// undocumented %r specifier
// used for good carriage return
// helps integrate loggers with repls
if (!__replmode) {
if (!__replmode || __nocolor) {
break;
} else {
s = "\r\033[K";
@ -845,12 +841,12 @@ privileged size_t kvsnprintf(char *b, size_t n, const char *fmt, va_list v) {
*/
privileged void kvprintf(const char *fmt, va_list v) {
size_t n;
char b[2048];
char b[4000];
struct Timestamps t;
if (!v) return;
t = kenter();
n = kformat(b, sizeof(b), fmt, v, t);
klog(b, MIN(n, sizeof(b)));
klog(b, MIN(n, sizeof(b) - 1));
kleave(t);
}

View file

@ -26,7 +26,7 @@
typedef char xmm_t __attribute__((__vector_size__(16), __aligned__(1)));
typedef long long xmm_a __attribute__((__vector_size__(16), __aligned__(16)));
noasan static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
if (IsAsan()) __asan_verify(p, n);
if (n <= 32) {
@ -44,8 +44,7 @@ noasan static dontinline antiquity void *memset_sse(char *p, char c, size_t n) {
return p;
}
noasan microarchitecture("avx") static void *memset_avx(char *p, char c,
size_t n) {
microarchitecture("avx") static void *memset_avx(char *p, char c, size_t n) {
char *t;
xmm_t v = {c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c};
if (IsAsan()) __asan_verify(p, n);

View file

@ -17,17 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
/**
* Controls disablement of MULTICS newlines.
*
* Normally we use `\n` for newlines. If this is `true` then we'll try
* our best to use `\r\n`. This is toggled automatically on Windows or
* when `ioctl(TCSETS)` disables `OPOST`.
*
* @see kprintf()
*/
char __nomultics;
/**
* Controls ANSI prefix for log emissions.
*

Some files were not shown because too many files have changed in this diff Show more