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

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