mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-07 10:20:29 +00:00
commit
b60fb4fb6f
551 changed files with 15948 additions and 7664 deletions
Binary file not shown.
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include "libc/runtime/symbols.internal.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// ShowCrashReports();
|
||||
ShowCrashReports();
|
||||
|
||||
if (IsDebuggerPresent(false)) {
|
||||
kprintf("debugger found!%n");
|
||||
|
|
|
@ -43,7 +43,6 @@ void PrintUri(const char *path) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
int i;
|
||||
while ((i = getopt(argc, argv, "?h")) != -1) {
|
||||
switch (i) {
|
||||
|
|
|
@ -140,7 +140,7 @@ o/$(MODE)/examples/nesemu1.com: \
|
|||
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
@$(COMPILE) -ASYMTAB o/$(MODE)/tool/build/symtab.com \
|
||||
-o o/$(MODE)/examples/.nesemu1/.symtab $<
|
||||
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -9qj $@ \
|
||||
@$(COMPILE) -AZIP -T$@ o/$(MODE)/third_party/zip/zip.com -0qj $@ \
|
||||
o/$(MODE)/examples/.nesemu1/.symtab
|
||||
|
||||
o/$(MODE)/examples/hello.com.dbg: \
|
||||
|
@ -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
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/gc.internal.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
|
@ -67,7 +68,7 @@ void PrintImg(const char *path) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
if (!NoDebug()) ShowCrashReports();
|
||||
int i;
|
||||
while ((i = getopt(argc, argv, "?huas01234")) != -1) {
|
||||
switch (i) {
|
||||
|
|
|
@ -153,7 +153,7 @@ void LoadWords(void) {
|
|||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
ShowCrashReports();
|
||||
if (!NoDebug()) ShowCrashReports();
|
||||
LoadWords();
|
||||
SpellChecker();
|
||||
return 0;
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/gdb.h"
|
||||
#include "libc/log/log.h"
|
||||
|
@ -152,7 +153,7 @@ void Draw(void) {
|
|||
int main(int argc, char *argv[]) {
|
||||
struct sigaction sa[2] = {{.sa_handler = OnShutdown},
|
||||
{.sa_handler = OnInvalidate}};
|
||||
ShowCrashReports();
|
||||
if (!NoDebug()) ShowCrashReports();
|
||||
Setup();
|
||||
Enter();
|
||||
GetTtySize();
|
||||
|
|
|
@ -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("");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,12 +36,12 @@ static void SetLimit(int resource, uint64_t soft, uint64_t hard) {
|
|||
lim.rlim_max = MIN(hard, old.rlim_max);
|
||||
lim.rlim_cur = MIN(soft, lim.rlim_max);
|
||||
if (!setrlimit(resource, &lim)) {
|
||||
fprintf(stderr, "%snote: setrlimit(%s) downgraded to {%,ld, %,ld}\n",
|
||||
fprintf(stderr, "%sNOTE: SETRLIMIT(%s) DOWNGRADED TO {%,ld, %,ld}\n",
|
||||
__strace_rlimit_name(resource), lim.rlim_cur, lim.rlim_max);
|
||||
return;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "error: setrlimit(%s, %,ld, %,ld) failed %m%n",
|
||||
fprintf(stderr, "ERROR: SETRLIMIT(%s, %,ld, %,ld) FAILED %m%n",
|
||||
__strace_rlimit_name(resource), soft, hard);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
for (i = 0; i < RLIM_NLIMITS; ++i) {
|
||||
rc = getrlimit(i, &rlim);
|
||||
printf("setrlimit(%-20s, %,16ld, %,16ld) → %d %s\n",
|
||||
printf("SETRLIMIT(%-20s, %,16ld, %,16ld) → %d %s\n",
|
||||
__strace_rlimit_name(i), rlim.rlim_cur, rlim.rlim_max, rc,
|
||||
!rc ? "" : strerror(errno));
|
||||
}
|
||||
|
|
|
@ -7,8 +7,9 @@
|
|||
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
||||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
|
||||
/**
|
||||
* @fileoverview Prints sequence of numbers.
|
||||
|
@ -16,6 +17,7 @@
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
long a, b, i;
|
||||
char buf[21], *p;
|
||||
switch (argc) {
|
||||
case 2:
|
||||
a = 1;
|
||||
|
@ -29,6 +31,9 @@ int main(int argc, char *argv[]) {
|
|||
return 1;
|
||||
}
|
||||
for (i = a; i <= b; ++i) {
|
||||
printf("%ld\n", i);
|
||||
p = buf;
|
||||
p = FormatInt64(p, i);
|
||||
*p++ = '\n';
|
||||
write(1, buf, p - buf);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ int main(int argc, char *argv[]) {
|
|||
long double real;
|
||||
char exebuf[PATH_MAX];
|
||||
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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,10 @@
|
|||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/sysv/consts/sig.h"
|
||||
|
||||
#define _POSIX_VERSION 200809L
|
||||
#define _POSIX2_VERSION _POSIX_VERSION
|
||||
#define _XOPEN_VERSION 700
|
||||
|
||||
#define EOF -1 /* end of file */
|
||||
#define WEOF -1u /* end of file (multibyte) */
|
||||
#define _IOFBF 0 /* fully buffered */
|
||||
|
@ -48,14 +52,14 @@
|
|||
#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
|
||||
#define S_ISSOCK(mode) (((mode)&S_IFMT) == S_IFSOCK)
|
||||
|
||||
#define WCOREDUMP(s) ((s)&0x80)
|
||||
#define WEXITSTATUS(s) (((s)&0xff00) >> 8)
|
||||
#define WCOREDUMP(s) (0x80 & (s))
|
||||
#define WEXITSTATUS(s) ((0xff00 & (s)) >> 8)
|
||||
#define WIFCONTINUED(s) ((s) == 0xffff)
|
||||
#define WIFEXITED(s) (!WTERMSIG(s))
|
||||
#define WIFSIGNALED(s) (((s)&0xffff) - 1u < 0xffu)
|
||||
#define WIFSTOPPED(s) ((short)((((s)&0xffff) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WIFSIGNALED(s) ((0xffff & (s)) - 1u < 0xffu)
|
||||
#define WIFSTOPPED(s) ((short)(((0xffff & (s)) * 0x10001) >> 8) > 0x7f00)
|
||||
#define WSTOPSIG(s) WEXITSTATUS(s)
|
||||
#define WTERMSIG(s) ((s)&0x7f)
|
||||
#define WTERMSIG(s) (127 & (s))
|
||||
#define W_STOPCODE(s) ((s) << 8 | 0177)
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
@ -75,7 +79,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 *);
|
||||
|
@ -119,14 +123,21 @@ int fsync(int);
|
|||
int ftruncate(int, int64_t);
|
||||
int getdents(unsigned, void *, unsigned, long *);
|
||||
int getdomainname(char *, size_t);
|
||||
int getegid(void) nosideeffect;
|
||||
int geteuid(void) nosideeffect;
|
||||
int getgid(void) nosideeffect;
|
||||
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 getuid(void) nosideeffect;
|
||||
int kill(int, int);
|
||||
int killpg(int, int);
|
||||
int link(const char *, const char *) dontthrow;
|
||||
|
@ -165,15 +176,18 @@ 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);
|
||||
int setresuid(uint32_t, uint32_t, uint32_t);
|
||||
int getresgid(uint32_t *, uint32_t *, uint32_t *);
|
||||
int getresuid(uint32_t *, uint32_t *, uint32_t *);
|
||||
int setreuid(uint32_t, uint32_t);
|
||||
int setrlimit(int, const struct rlimit *);
|
||||
int setsid(void);
|
||||
|
@ -192,6 +206,7 @@ int sysinfo(struct sysinfo *);
|
|||
int touch(const char *, uint32_t);
|
||||
int truncate(const char *, uint64_t);
|
||||
int ttyname_r(int, char *, size_t);
|
||||
int umask(int);
|
||||
int uname(struct utsname *);
|
||||
int unlink(const char *);
|
||||
int unlink_s(const char **);
|
||||
|
@ -206,9 +221,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);
|
||||
|
@ -222,17 +237,10 @@ ssize_t splice(int, int64_t *, int, int64_t *, size_t, uint32_t);
|
|||
ssize_t vmsplice(int, const struct iovec *, int64_t, uint32_t);
|
||||
ssize_t write(int, const void *, size_t);
|
||||
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 pledge(const char *, const char *);
|
||||
|
||||
int clone(int (*)(void *), void *, size_t, int, void *, int *, void *, size_t,
|
||||
int *);
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ $(LIBC_CALLS_A).pkg: \
|
|||
$(LIBC_CALLS_A_OBJS) \
|
||||
$(foreach x,$(LIBC_CALLS_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
o/$(MODE)/libc/calls/vdsofunc.greg.o \
|
||||
o/$(MODE)/libc/calls/directmap.o \
|
||||
o/$(MODE)/libc/calls/directmap-nt.o \
|
||||
o/$(MODE)/libc/calls/raise.o: \
|
||||
|
@ -108,9 +109,12 @@ o//libc/calls/fcntl.o: \
|
|||
o/$(MODE)/libc/calls/execl.o \
|
||||
o/$(MODE)/libc/calls/execle.o \
|
||||
o/$(MODE)/libc/calls/execlp.o \
|
||||
o/$(MODE)/libc/calls/copyfile.o \
|
||||
o/$(MODE)/libc/calls/execve-nt.o \
|
||||
o/$(MODE)/libc/calls/execve-sysv.o \
|
||||
o/$(MODE)/libc/calls/symlinkat-nt.o \
|
||||
o/$(MODE)/libc/calls/readlinkat-nt.o \
|
||||
o/$(MODE)/libc/calls/describeopenflags.greg.o \
|
||||
o/$(MODE)/libc/calls/mkntenvblock.o: \
|
||||
OVERRIDE_CPPFLAGS += \
|
||||
-DSTACK_FRAME_UNLIMITED
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
static typeof(sys_clock_gettime) *__clock_gettime = sys_clock_gettime;
|
||||
|
||||
/**
|
||||
* Returns nanosecond time.
|
||||
*
|
||||
|
@ -52,7 +54,7 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
|
|||
rc = einval();
|
||||
} else if (!IsWindows()) {
|
||||
e = errno;
|
||||
if ((rc = sys_clock_gettime(clockid, ts))) {
|
||||
if ((rc = __clock_gettime(clockid, ts))) {
|
||||
errno = e;
|
||||
ad = sys_gettimeofday((struct timeval *)ts, NULL, NULL);
|
||||
assert(ad.ax != -1);
|
||||
|
@ -72,3 +74,23 @@ noinstrument int clock_gettime(int clockid, struct timespec *ts) {
|
|||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns fast system clock_gettime() if it exists.
|
||||
*/
|
||||
void *__get_clock_gettime(void) {
|
||||
void *vdso;
|
||||
static bool once;
|
||||
static void *result;
|
||||
if (!once) {
|
||||
if ((vdso = __vdsofunc("__vdso_clock_gettime"))) {
|
||||
__clock_gettime = result = vdso;
|
||||
}
|
||||
once = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const void *const __clock_gettime_ctor[] initarray = {
|
||||
__get_clock_gettime,
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "libc/nt/enum/filesharemode.h"
|
||||
#include "libc/nt/files.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/filetime.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/madv.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
|
|
38
libc/calls/describeclockname.c
Normal file
38
libc/calls/describeclockname.c
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*-*- 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/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
/**
|
||||
* Describes clock_gettime() clock argument.
|
||||
*/
|
||||
char *DescribeClockName(int x) {
|
||||
int i;
|
||||
char *s;
|
||||
_Alignas(char) static char buf[32];
|
||||
if ((s = GetMagnumStr(kClockNames, x))) {
|
||||
stpcpy(stpcpy(buf, "CLOCK_"), s);
|
||||
return buf;
|
||||
} else {
|
||||
FormatInt32(buf, x);
|
||||
return buf;
|
||||
}
|
||||
}
|
41
libc/calls/describeopenflags.greg.c
Normal file
41
libc/calls/describeopenflags.greg.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 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/itoa.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/describeflags.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
|
||||
/**
|
||||
* Describes clock_gettime() clock argument.
|
||||
*/
|
||||
char *DescribeOpenFlags(int x) {
|
||||
char *s;
|
||||
int i, n;
|
||||
struct DescribeFlags *d;
|
||||
_Alignas(char) static char openflags[128];
|
||||
// TODO(jart): unify DescribeFlags and MagnumStr data structures
|
||||
for (n = 0; kOpenFlags[n].x != MAGNUM_TERMINATOR;) ++n;
|
||||
d = alloca(n * sizeof(struct DescribeFlags));
|
||||
for (i = 0; i < n; ++i) {
|
||||
d[i].flag = MAGNUM_NUMBER(kOpenFlags, i);
|
||||
d[i].name = MAGNUM_STRING(kOpenFlags, i);
|
||||
}
|
||||
return DescribeFlags(openflags, sizeof(openflags), d, n, "O_", x);
|
||||
}
|
|
@ -40,7 +40,7 @@ int execlp(const char *prog, const char *arg, ... /*, NULL*/) {
|
|||
char **argv;
|
||||
va_list va, vb;
|
||||
char pathbuf[PATH_MAX];
|
||||
if (!(exe = commandv(prog, pathbuf))) return -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;
|
||||
|
|
|
@ -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), PATH_MAX),
|
||||
_PATH_BSHELL);
|
||||
} else {
|
||||
shargs[0] = _PATH_BSHELL;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -38,6 +38,6 @@ int execvpe(const char *prog, char *const argv[], char *const *envp) {
|
|||
char *exe;
|
||||
char pathbuf[PATH_MAX];
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int sys_faccessat_nt(int dirfd, const char *path, int mode, uint32_t flags) {
|
||||
textwindows int sys_faccessat_nt(int dirfd, const char *path, int mode,
|
||||
uint32_t flags) {
|
||||
char16_t path16[PATH_MAX];
|
||||
if (__mkntpathat(dirfd, path, 0, path16) == -1) return -1;
|
||||
return __fix_enotdir(ntaccesscheck(path16, mode), path16);
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
* file is a relative path, then file is opened relative to dirfd
|
||||
* @param path is a filename or directory
|
||||
* @param mode can be R_OK, W_OK, X_OK, F_OK
|
||||
* @param flags should be 0
|
||||
* @param flags can have AT_EACCESS, AT_SYMLINK_NOFOLLOW
|
||||
* @return 0 if ok, or -1 and sets errno
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
|
|
|
@ -106,7 +106,7 @@ textwindows int sys_fstat_nt(int64_t handle, struct stat *st) {
|
|||
st->st_size = (uint64_t)wst.nFileSizeHigh << 32 | wst.nFileSizeLow;
|
||||
st->st_blksize = PAGESIZE;
|
||||
st->st_dev = wst.dwVolumeSerialNumber;
|
||||
st->st_rdev = wst.dwVolumeSerialNumber;
|
||||
st->st_rdev = 0;
|
||||
st->st_ino = (uint64_t)wst.nFileIndexHigh << 32 | wst.nFileIndexLow;
|
||||
st->st_nlink = wst.nNumberOfLinks;
|
||||
if (S_ISLNK(st->st_mode)) {
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
*/
|
||||
int32_t sys_fstatat(int32_t dirfd, const char *path, struct stat *st,
|
||||
int32_t flags) {
|
||||
int rc;
|
||||
void *p;
|
||||
union metastat ms;
|
||||
if (IsAsan() && !__asan_is_valid(path, 1)) return efault();
|
||||
|
|
|
@ -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];
|
||||
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;
|
||||
|
|
|
@ -51,7 +51,7 @@ char *getcwd(char *buf, size_t size) {
|
|||
}
|
||||
} else if (weaken(malloc)) {
|
||||
assert(!__vforked);
|
||||
if (!size) size = PATH_MAX + 1;
|
||||
if (!size) size = PATH_MAX;
|
||||
if (!(p = weaken(malloc)(size))) {
|
||||
STRACE("getcwd(%p, %'zu) %m", buf, size);
|
||||
return 0;
|
||||
|
|
|
@ -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 getegid(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_getegid();
|
||||
} else {
|
||||
rc = getgid();
|
||||
}
|
||||
STRACE("%s() → %d% m", "getegid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,15 @@
|
|||
|
||||
/**
|
||||
* Returns effective user ID of calling process.
|
||||
* @return user id
|
||||
*/
|
||||
uint32_t geteuid(void) {
|
||||
int geteuid(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_geteuid();
|
||||
} else {
|
||||
rc = getuid();
|
||||
}
|
||||
STRACE("%s() → %d% m", "geteuid", rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -16,28 +16,15 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/str/path.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/tpenc.h"
|
||||
#include "libc/str/utf16.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
|
||||
#define SIZE 1024
|
||||
#define CTL_KERN 1
|
||||
|
@ -45,97 +32,90 @@
|
|||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
#define KERN_PROC_PATHNAME_NETBSD 5
|
||||
|
||||
char program_executable_name[SIZE];
|
||||
char program_executable_name[PATH_MAX];
|
||||
|
||||
static textwindows bool GetNtExePath(char exe[SIZE]) {
|
||||
bool32 rc;
|
||||
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);
|
||||
if (!rc) return false;
|
||||
for (i = j = 0; (x = path16[i++] & 0xffff);) {
|
||||
if (!IsUcs2(x)) {
|
||||
y = path16[i++] & 0xffff;
|
||||
x = MergeUtf16(x, y);
|
||||
}
|
||||
if (x == '\\') x = '/';
|
||||
w = tpenc(x);
|
||||
do {
|
||||
exe[j] = w;
|
||||
if (++j == SIZE) {
|
||||
return false;
|
||||
}
|
||||
} while ((w >>= 8));
|
||||
}
|
||||
exe[j] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void ReadProgramExecutableName(char exe[SIZE], char *argv0,
|
||||
uintptr_t *auxv) {
|
||||
int e;
|
||||
size_t m;
|
||||
ssize_t n;
|
||||
static inline void GetProgramExecutableNameImpl(char *p, char *e) {
|
||||
char *q;
|
||||
ssize_t rc;
|
||||
size_t i, n;
|
||||
union {
|
||||
int cmd[4];
|
||||
char *p, *t;
|
||||
e = errno;
|
||||
if (!IsWindows() || !GetNtExePath(exe)) {
|
||||
for (p = 0; *auxv; auxv += 2) {
|
||||
if (*auxv == AT_EXECFN) {
|
||||
p = (char *)auxv[1];
|
||||
break;
|
||||
char16_t path16[PATH_MAX];
|
||||
} u;
|
||||
|
||||
if (IsWindows()) {
|
||||
n = GetModuleFileName(0, u.path16, ARRAYLEN(u.path16));
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (u.path16[i] == '\\') {
|
||||
u.path16[i] = '/';
|
||||
}
|
||||
}
|
||||
n = 0;
|
||||
if (!p) p = argv0;
|
||||
if (p) {
|
||||
if (!_isabspath(p)) {
|
||||
if (getcwd(exe, SIZE - 1)) {
|
||||
n = strlen(exe);
|
||||
exe[n++] = '/';
|
||||
if (isalpha(u.path16[0]) && u.path16[1] == ':' && u.path16[2] == '/') {
|
||||
p[0] = '/';
|
||||
p[1] = '/';
|
||||
p[2] = '?';
|
||||
p[3] = '/';
|
||||
p += 4;
|
||||
}
|
||||
tprecode16to8(p, e - p, u.path16);
|
||||
return;
|
||||
}
|
||||
|
||||
if (__argc && (q = __argv[0]) && !sys_faccessat(AT_FDCWD, q, F_OK, 0)) {
|
||||
if (*q != '/') {
|
||||
if (q[0] == '.' && q[1] == '/') {
|
||||
q += 2;
|
||||
}
|
||||
if (getcwd(p, e - p)) {
|
||||
while (*p) ++p;
|
||||
*p++ = '/';
|
||||
}
|
||||
}
|
||||
for (; *p; ++p) {
|
||||
if (n + 1 < SIZE) {
|
||||
exe[n++] = *p;
|
||||
for (i = 0; *q && p + 1 < e; ++p, ++q) {
|
||||
*p = *q;
|
||||
}
|
||||
*p = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if ((rc = sys_readlinkat(AT_FDCWD, "/proc/self/exe", p, e - p - 1)) > 0 ||
|
||||
(rc = sys_readlinkat(AT_FDCWD, "/proc/curproc/file", p, e - p - 1)) > 0) {
|
||||
p[rc] = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsFreebsd() || IsNetbsd()) {
|
||||
u.cmd[0] = CTL_KERN;
|
||||
u.cmd[1] = KERN_PROC;
|
||||
if (IsFreebsd()) {
|
||||
u.cmd[2] = KERN_PROC_PATHNAME_FREEBSD;
|
||||
} else {
|
||||
u.cmd[2] = KERN_PROC_PATHNAME_NETBSD;
|
||||
}
|
||||
u.cmd[3] = -1; // current process
|
||||
n = e - p;
|
||||
if (sysctl(u.cmd, ARRAYLEN(u.cmd), p, &n, 0, 0) != -1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
exe[n] = 0;
|
||||
}
|
||||
errno = e;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns absolute path of executable.
|
||||
*
|
||||
* This variable is initialized automatically at startup. The path is
|
||||
* basically `argv[0]` except some extra vetting is done to provide
|
||||
* stronger assurance that the path can be counted upon to exist.
|
||||
*
|
||||
* For example, if your program is executed as a relative path and then
|
||||
* your program calls `chdir()`, then `argv[0]` will be incorrect; but
|
||||
* `program_executable_name` will work, because it prefixed `getcwd()`
|
||||
* early in the initialization phase.
|
||||
*
|
||||
* @see GetInterpreterExecutableName()
|
||||
* @see program_invocation_short_name
|
||||
* @see program_invocation_name
|
||||
*/
|
||||
char *GetProgramExecutableName(void) {
|
||||
int e;
|
||||
static bool once;
|
||||
if (!once) {
|
||||
ReadProgramExecutableName(program_executable_name, __argv[0], __auxv);
|
||||
once = true;
|
||||
e = errno;
|
||||
GetProgramExecutableNameImpl(
|
||||
program_executable_name,
|
||||
program_executable_name + sizeof(program_executable_name));
|
||||
errno = e;
|
||||
}
|
||||
return program_executable_name;
|
||||
}
|
||||
|
||||
// try our best to memoize it before a chdir() happens
|
||||
const void *const program_executable_name_init_ctor[] initarray = {
|
||||
const void *const GetProgramExecutableNameCtor[] initarray = {
|
||||
GetProgramExecutableName,
|
||||
};
|
|
@ -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();
|
||||
|
|
51
libc/calls/getresgid.c
Normal file
51
libc/calls/getresgid.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Gets real, effective, and "saved" group ids.
|
||||
*
|
||||
* @param real receives real user id, or null to do nothing
|
||||
* @param effective receives effective user id, or null to do nothing
|
||||
* @param saved receives saved user id, or null to do nothing
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see setresuid()
|
||||
*/
|
||||
int getresgid(uint32_t *real, uint32_t *effective, uint32_t *saved) {
|
||||
int rc, gid;
|
||||
if (IsWindows()) {
|
||||
gid = getgid();
|
||||
if (real) *real = gid;
|
||||
if (effective) *effective = gid;
|
||||
if (saved) *saved = gid;
|
||||
rc = 0;
|
||||
} else if (saved) {
|
||||
rc = sys_getresgid(real, effective, saved);
|
||||
} else {
|
||||
if (real) *real = sys_getgid();
|
||||
if (effective) *effective = sys_getegid();
|
||||
rc = 0;
|
||||
}
|
||||
STRACE("getresgid([%d], [%d], [%d]) → %d% m", real ? *real : 0,
|
||||
effective ? *effective : 0, saved ? *saved : 0, rc);
|
||||
return rc;
|
||||
}
|
51
libc/calls/getresuid.c
Normal file
51
libc/calls/getresuid.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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"
|
||||
#include "libc/dce.h"
|
||||
|
||||
/**
|
||||
* Gets real, effective, and "saved" user ids.
|
||||
*
|
||||
* @param real receives real user id, or null to do nothing
|
||||
* @param effective receives effective user id, or null to do nothing
|
||||
* @param saved receives saved user id, or null to do nothing
|
||||
* @return 0 on success or -1 w/ errno
|
||||
* @see setresuid()
|
||||
*/
|
||||
int getresuid(uint32_t *real, uint32_t *effective, uint32_t *saved) {
|
||||
int rc, uid;
|
||||
if (IsWindows()) {
|
||||
uid = getuid();
|
||||
if (real) *real = uid;
|
||||
if (effective) *effective = uid;
|
||||
if (saved) *saved = uid;
|
||||
rc = 0;
|
||||
} else if (saved) {
|
||||
rc = sys_getresuid(real, effective, saved);
|
||||
} else {
|
||||
if (real) *real = sys_getuid();
|
||||
if (effective) *effective = sys_geteuid();
|
||||
rc = 0;
|
||||
}
|
||||
STRACE("getresuid([%d], [%d], [%d]) → %d% m", real ? *real : 0,
|
||||
effective ? *effective : 0, saved ? *saved : 0, rc);
|
||||
return rc;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/time/struct/timezone.h"
|
||||
|
||||
int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
|
||||
textwindows int sys_gettimeofday_nt(struct timeval *tv, struct timezone *tz) {
|
||||
struct NtFileTime ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
if (tv) *tv = FileTimeToTimeVal(ft);
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include "libc/time/struct/timezone.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static typeof(sys_gettimeofday) *__gettimeofday = sys_gettimeofday;
|
||||
|
||||
/**
|
||||
* Returns system wall time in microseconds.
|
||||
*
|
||||
|
@ -40,7 +42,7 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
|||
return efault();
|
||||
}
|
||||
if (!IsWindows() && !IsMetal()) {
|
||||
ad = sys_gettimeofday(tv, tz, NULL);
|
||||
ad = __gettimeofday(tv, tz, NULL);
|
||||
assert(ad.ax != -1);
|
||||
if (SupportsXnu() && ad.ax && tv) {
|
||||
tv->tv_sec = ad.ax;
|
||||
|
@ -53,3 +55,14 @@ int gettimeofday(struct timeval *tv, struct timezone *tz) {
|
|||
return sys_gettimeofday_nt(tv, tz);
|
||||
}
|
||||
}
|
||||
|
||||
static textstartup void __gettimeofday_init(void) {
|
||||
void *vdso;
|
||||
if ((vdso = __vdsofunc("__vdso_gettimeofday"))) {
|
||||
__gettimeofday = vdso;
|
||||
}
|
||||
}
|
||||
|
||||
const void *const __gettimeofday_ctor[] initarray = {
|
||||
__gettimeofday_init,
|
||||
};
|
||||
|
|
|
@ -51,7 +51,7 @@ static textwindows dontinline uint32_t GetUserNameHash(void) {
|
|||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
uint32_t getuid(void) {
|
||||
int getuid(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_getuid();
|
||||
|
@ -71,7 +71,7 @@ uint32_t getuid(void) {
|
|||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
uint32_t getgid(void) {
|
||||
int getgid(void) {
|
||||
int rc;
|
||||
if (!IsWindows()) {
|
||||
rc = sys_getgid();
|
||||
|
|
|
@ -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;
|
||||
|
@ -163,8 +163,11 @@ i32 sys_getpgid(i32) hidden;
|
|||
i32 sys_getpgrp(void) hidden;
|
||||
i32 sys_getppid(void) hidden;
|
||||
i32 sys_getpriority(i32, u32) hidden;
|
||||
i32 sys_getresgid(u32 *, u32 *, u32 *);
|
||||
i32 sys_getresuid(u32 *, u32 *, u32 *);
|
||||
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;
|
||||
|
@ -183,6 +186,7 @@ i32 sys_openat(i32, const char *, i32, u32) hidden;
|
|||
i32 sys_pause(void) hidden;
|
||||
i32 sys_pipe(i32[hasatleast 2]) hidden;
|
||||
i32 sys_pipe2(i32[hasatleast 2], u32) hidden;
|
||||
i32 sys_pledge(const char *, const char *) hidden;
|
||||
i32 sys_posix_openpt(i32) hidden;
|
||||
i32 sys_renameat(i32, const char *, i32, const char *) hidden;
|
||||
i32 sys_sched_setaffinity(i32, u64, const void *) hidden;
|
||||
|
@ -191,8 +195,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_setresgid(uint32_t, uint32_t, uint32_t) hidden;
|
||||
i32 sys_setresuid(uint32_t, uint32_t, uint32_t) hidden;
|
||||
i32 sys_setregid(u32, u32) hidden;
|
||||
i32 sys_setresgid(u32, u32, u32) hidden;
|
||||
i32 sys_setresuid(u32, u32, u32) 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 +236,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;
|
||||
|
@ -243,6 +248,8 @@ void sys_exit(int) hidden;
|
|||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
void __onfork(void) hidden;
|
||||
void *__vdsofunc(const char *) hidden;
|
||||
void *__get_clock_gettime(void) hidden;
|
||||
i32 __fixupnewfd(i32, i32) hidden;
|
||||
void __restore_rt() hidden;
|
||||
int sys_utimensat_xnu(int, const char *, const struct timespec *, int) hidden;
|
||||
|
@ -326,6 +333,7 @@ int ioctl_tiocgwinsz_nt(struct Fd *, struct winsize *) hidden;
|
|||
│ cosmopolitan § syscalls » windows nt » support ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
bool __is_linux_2_6_23(void) hidden;
|
||||
int64_t __fix_enotdir(int64_t, char16_t *) hidden;
|
||||
int64_t __fix_enotdir3(int64_t, char16_t *, char16_t *) hidden;
|
||||
bool _check_interrupts(bool, struct Fd *) hidden;
|
||||
|
@ -337,9 +345,9 @@ 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]) hidden;
|
||||
int __mkntpath2(const char *, char16_t[hasatleast PATH_MAX], int) hidden;
|
||||
int __mkntpathat(int, const char *, int, char16_t[hasatleast PATH_MAX]) 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));
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
32
libc/calls/islinux.c
Normal file
32
libc/calls/islinux.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*-*- 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/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/pr.h"
|
||||
|
||||
bool __is_linux_2_6_23(void) {
|
||||
int rc;
|
||||
if (!IsLinux()) return false;
|
||||
asm volatile("syscall"
|
||||
: "=a"(rc)
|
||||
: "0"(157), "D"(PR_GET_SECCOMP)
|
||||
: "rcx", "r11", "memory");
|
||||
return rc != -EINVAL;
|
||||
}
|
47
libc/calls/kclocknames.S
Normal file
47
libc/calls/kclocknames.S
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 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"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kClockNames
|
||||
.long 1f - kClockNames
|
||||
.rodata.str1.1
|
||||
1: .string "\s"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kClockNames:
|
||||
.e CLOCK_REALTIME,"REALTIME"
|
||||
.e CLOCK_MONOTONIC,"MONOTONIC"
|
||||
.e CLOCK_MONOTONIC_RAW,"MONOTONIC_RAW"
|
||||
.e CLOCK_REALTIME_COARSE,"REALTIME_COARSE"
|
||||
.e CLOCK_MONOTONIC_COARSE,"MONOTONIC_COARSE"
|
||||
.e CLOCK_PROCESS_CPUTIME_ID,"PROCESS_CPUTIME_ID"
|
||||
.e CLOCK_TAI,"TAI"
|
||||
.e CLOCK_PROF,"PROF"
|
||||
.e CLOCK_BOOTTIME,"BOOTTIME"
|
||||
.e CLOCK_REALTIME_ALARM,"REALTIME_ALARM"
|
||||
.e CLOCK_BOOTTIME_ALARM,"BOOTTIME_ALARM"
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kClockNames,globl,hidden
|
||||
.overrun
|
65
libc/calls/kopenflags.S
Normal file
65
libc/calls/kopenflags.S
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 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"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
.macro .e e s
|
||||
.long \e - kOpenFlags
|
||||
.long 1f - kOpenFlags
|
||||
.rodata.str1.1
|
||||
1: .string "\s"
|
||||
.previous
|
||||
.endm
|
||||
|
||||
.section .rodata
|
||||
.align 4
|
||||
.underrun
|
||||
kOpenFlags:
|
||||
.e O_RDWR,"RDWR" // order matters
|
||||
.e O_RDONLY,"RDONLY" //
|
||||
.e O_WRONLY,"WRONLY" //
|
||||
.e O_ACCMODE,"ACCMODE" // mask of prev three
|
||||
.e O_CREAT,"CREAT" //
|
||||
.e O_EXCL,"EXCL" //
|
||||
.e O_TRUNC,"TRUNC" //
|
||||
.e O_CLOEXEC,"CLOEXEC" //
|
||||
.e O_NONBLOCK,"NONBLOCK" //
|
||||
.e O_DIRECT,"DIRECT" // no-op on xnu/openbsd
|
||||
.e O_APPEND,"APPEND" // weird on nt
|
||||
.e O_TMPFILE,"TMPFILE" // linux, windows
|
||||
.e O_NOFOLLOW,"NOFOLLOW" // unix
|
||||
.e O_SYNC,"SYNC" // unix
|
||||
.e O_ASYNC,"ASYNC" // unix
|
||||
.e O_NOCTTY,"NOCTTY" // unix
|
||||
.e O_NOATIME,"NOATIME" // linux
|
||||
.e O_EXEC,"EXEC" // free/openbsd
|
||||
.e O_SEARCH,"SEARCH" // free/netbsd
|
||||
.e O_DSYNC,"DSYNC" // linux/xnu/open/netbsd
|
||||
.e O_RSYNC,"RSYNC" // linux/open/netbsd
|
||||
.e O_PATH,"PATH" // linux
|
||||
.e O_VERIFY,"VERIFY" // freebsd
|
||||
.e O_SHLOCK,"SHLOCK" // bsd
|
||||
.e O_EXLOCK,"EXLOCK" // bsd
|
||||
.e O_RANDOM,"RANDOM" // windows
|
||||
.e O_SEQUENTIAL,"SEQUENTIAL" // windows
|
||||
.e O_COMPRESSED,"COMPRESSED" // windows
|
||||
.e O_INDEXED,"INDEXED" // windows
|
||||
.long MAGNUM_TERMINATOR
|
||||
.endobj kOpenFlags,globl,hidden
|
||||
.overrun
|
|
@ -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()
|
||||
*/
|
||||
|
|
|
@ -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];
|
||||
/* 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);
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#define APPEND(c) \
|
||||
do { \
|
||||
cmdline[k++] = c; \
|
||||
if (k == ARG_MAX) return e2big(); \
|
||||
if (k == ARG_MAX / 2) { \
|
||||
return e2big(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static noasan bool NeedsQuotes(const char *s) {
|
||||
|
@ -52,8 +54,8 @@ static noasan bool NeedsQuotes(const char *s) {
|
|||
* @return freshly allocated lpCommandLine or NULL w/ errno
|
||||
* @see libc/runtime/dosargv.c
|
||||
*/
|
||||
textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX], const char *prog,
|
||||
char *const argv[]) {
|
||||
textwindows noasan int mkntcmdline(char16_t cmdline[ARG_MAX / 2],
|
||||
const char *prog, char *const argv[]) {
|
||||
char *arg;
|
||||
uint64_t w;
|
||||
wint_t x, y;
|
||||
|
|
|
@ -55,9 +55,9 @@ static noasan void InsertString(char **a, size_t i, char *s) {
|
|||
* @param envp is an a NULL-terminated array of UTF-8 strings
|
||||
* @param extravar is a VAR=val string we consider part of envp or NULL
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @error E2BIG if total number of shorts exceeded ARG_MAX (0x8000)
|
||||
* @error E2BIG if total number of shorts exceeded ARG_MAX/2 (32767)
|
||||
*/
|
||||
textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
|
||||
textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX / 2],
|
||||
char *const envp[], const char *extravar) {
|
||||
bool v;
|
||||
char *t;
|
||||
|
@ -98,7 +98,9 @@ textwindows noasan int mkntenvblock(char16_t envvars[ARG_MAX],
|
|||
w = EncodeUtf16(x);
|
||||
do {
|
||||
envvars[k++] = w & 0xffff;
|
||||
if (k == ARG_MAX) return e2big();
|
||||
if (k == ARG_MAX / 2) {
|
||||
return e2big();
|
||||
}
|
||||
} while ((w >>= 16));
|
||||
} while (x);
|
||||
}
|
||||
|
|
|
@ -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]) {
|
||||
return __mkntpath2(path, path16, -1);
|
||||
}
|
||||
|
||||
|
@ -67,14 +68,13 @@ textwindows int __mkntpath(const char *path,
|
|||
* @error ENAMETOOLONG
|
||||
*/
|
||||
textwindows int __mkntpath2(const char *path,
|
||||
char16_t path16[hasatleast PATH_MAX - 16],
|
||||
int flags) {
|
||||
char16_t path16[hasatleast PATH_MAX], 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 +83,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);
|
||||
|
@ -95,7 +100,7 @@ textwindows int __mkntpath2(const char *path,
|
|||
m = 0;
|
||||
}
|
||||
n = tprecode8to16(p, z, q).ax;
|
||||
if (n == z - 1) {
|
||||
if (n >= z - 1) {
|
||||
STRACE("path too long for windows: %#s", path);
|
||||
return enametoolong();
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int __mkntpathat(int dirfd, const char *path, int flags,
|
||||
char16_t file[PATH_MAX]) {
|
||||
char16_t file[hasatleast PATH_MAX]) {
|
||||
char16_t dir[PATH_MAX];
|
||||
uint32_t dirlen, filelen;
|
||||
if ((filelen = __mkntpath2(path, file, flags)) == -1) return -1;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -31,9 +31,9 @@
|
|||
#include "libc/time/time.h"
|
||||
|
||||
static struct Now {
|
||||
bool once;
|
||||
uint64_t k0;
|
||||
long double r0, cpn;
|
||||
typeof(sys_clock_gettime) *clock_gettime;
|
||||
} g_now;
|
||||
|
||||
static long double GetTimeSample(void) {
|
||||
|
@ -73,22 +73,39 @@ void RefreshTime(void) {
|
|||
now.cpn = MeasureNanosPerCycle();
|
||||
now.r0 = dtime(CLOCK_REALTIME);
|
||||
now.k0 = rdtsc();
|
||||
now.once = true;
|
||||
memcpy(&g_now, &now, sizeof(now));
|
||||
}
|
||||
|
||||
long double ConvertTicksToNanos(uint64_t ticks) {
|
||||
if (!g_now.once) RefreshTime();
|
||||
return ticks * g_now.cpn; /* pico scale */
|
||||
}
|
||||
|
||||
long double nowl_sys(void) {
|
||||
static long double nowl_sys(void) {
|
||||
return dtime(CLOCK_REALTIME);
|
||||
}
|
||||
|
||||
long double nowl_art(void) {
|
||||
uint64_t ticks;
|
||||
if (!g_now.once) RefreshTime();
|
||||
ticks = unsignedsubtract(rdtsc(), g_now.k0);
|
||||
static long double nowl_art(void) {
|
||||
uint64_t ticks = rdtsc() - g_now.k0;
|
||||
return g_now.r0 + (1 / 1e9L * (ticks * g_now.cpn));
|
||||
}
|
||||
|
||||
static long double nowl_vdso(void) {
|
||||
long double secs;
|
||||
struct timespec tv;
|
||||
g_now.clock_gettime(CLOCK_REALTIME, &tv);
|
||||
secs = tv.tv_nsec;
|
||||
secs *= 1 / 1e9L;
|
||||
secs += tv.tv_sec;
|
||||
return secs;
|
||||
}
|
||||
|
||||
long double nowl_setup(void) {
|
||||
uint64_t ticks;
|
||||
if ((g_now.clock_gettime = __get_clock_gettime())) {
|
||||
nowl = nowl_vdso;
|
||||
} else if (X86_HAVE(INVTSC)) {
|
||||
RefreshTime();
|
||||
nowl = nowl_art;
|
||||
} else {
|
||||
nowl = nowl_sys;
|
||||
}
|
||||
return nowl();
|
||||
}
|
||||
|
||||
long double (*nowl)(void) = nowl_setup;
|
||||
|
|
|
@ -32,8 +32,13 @@
|
|||
#include "libc/nt/struct/startupinfo.h"
|
||||
|
||||
struct SpawnBlock {
|
||||
char16_t cmdline[ARG_MAX];
|
||||
char16_t envvars[ARG_MAX];
|
||||
union {
|
||||
struct {
|
||||
char16_t cmdline[ARG_MAX / 2];
|
||||
char16_t envvars[ARG_MAX / 2];
|
||||
};
|
||||
char __pad[ROUNDUP(ARG_MAX / 2 * 2 * sizeof(char16_t), FRAMESIZE)];
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -68,20 +73,15 @@ textwindows int ntspawn(
|
|||
struct NtProcessInformation *opt_out_lpProcessInformation) {
|
||||
int rc;
|
||||
int64_t handle;
|
||||
size_t blocksize;
|
||||
struct SpawnBlock *block;
|
||||
char16_t prog16[PATH_MAX];
|
||||
rc = -1;
|
||||
block = NULL;
|
||||
if (__mkntpath(prog, prog16) == -1) return -1;
|
||||
blocksize = ROUNDUP(sizeof(*block), FRAMESIZE);
|
||||
if ((handle = CreateFileMapping(
|
||||
-1,
|
||||
&(struct NtSecurityAttributes){sizeof(struct NtSecurityAttributes),
|
||||
NULL, false},
|
||||
pushpop(kNtPageReadwrite), 0, blocksize, NULL)) &&
|
||||
if ((handle = CreateFileMapping(-1, 0, pushpop(kNtPageReadwrite), 0,
|
||||
sizeof(*block), 0)) &&
|
||||
(block = MapViewOfFileEx(handle, kNtFileMapRead | kNtFileMapWrite, 0, 0,
|
||||
blocksize, NULL)) &&
|
||||
sizeof(*block), 0)) &&
|
||||
mkntcmdline(block->cmdline, prog, argv) != -1 &&
|
||||
mkntenvblock(block->envvars, envp, extravar) != -1 &&
|
||||
CreateProcess(prog16, block->cmdline, opt_lpProcessAttributes,
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
int mkntcmdline(char16_t[ARG_MAX], const char *, char *const[]) hidden;
|
||||
int mkntenvblock(char16_t[ARG_MAX], char *const[], const char *) hidden;
|
||||
int mkntcmdline(char16_t[ARG_MAX / 2], const char *, char *const[]) hidden;
|
||||
int mkntenvblock(char16_t[ARG_MAX / 2], char *const[], const char *) hidden;
|
||||
int ntspawn(const char *, char *const[], char *const[], const char *,
|
||||
struct NtSecurityAttributes *, struct NtSecurityAttributes *,
|
||||
bool32, uint32_t, const char16_t *, const struct NtStartupInfo *,
|
||||
|
|
83
libc/calls/oldbench.c
Normal file
83
libc/calls/oldbench.c
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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/bits/bits.h"
|
||||
#include "libc/bits/initializer.internal.h"
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/nexgen32e/rdtsc.h"
|
||||
#include "libc/nexgen32e/x86feature.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/clock.h"
|
||||
#include "libc/time/time.h"
|
||||
|
||||
static struct Now {
|
||||
bool once;
|
||||
uint64_t k0;
|
||||
long double r0, cpn;
|
||||
} g_now;
|
||||
|
||||
static long double GetTimeSample(void) {
|
||||
uint64_t tick1, tick2;
|
||||
long double time1, time2;
|
||||
sched_yield();
|
||||
time1 = dtime(CLOCK_REALTIME);
|
||||
tick1 = rdtsc();
|
||||
nanosleep(&(struct timespec){0, 1000000}, NULL);
|
||||
time2 = dtime(CLOCK_REALTIME);
|
||||
tick2 = rdtsc();
|
||||
return (time2 - time1) * 1e9 / MAX(1, tick2 - tick1);
|
||||
}
|
||||
|
||||
static long double MeasureNanosPerCycle(void) {
|
||||
bool tc;
|
||||
int i, n;
|
||||
long double avg, samp;
|
||||
tc = __time_critical;
|
||||
__time_critical = true;
|
||||
if (IsWindows()) {
|
||||
n = 30;
|
||||
} else {
|
||||
n = 20;
|
||||
}
|
||||
for (avg = 1.0L, i = 1; i < n; ++i) {
|
||||
samp = GetTimeSample();
|
||||
avg += (samp - avg) / i;
|
||||
}
|
||||
__time_critical = tc;
|
||||
STRACE("MeasureNanosPerCycle cpn*1000=%d", (long)(avg * 1000));
|
||||
return avg;
|
||||
}
|
||||
|
||||
static void Refresh(void) {
|
||||
struct Now now;
|
||||
now.cpn = MeasureNanosPerCycle();
|
||||
now.r0 = dtime(CLOCK_REALTIME);
|
||||
now.k0 = rdtsc();
|
||||
now.once = true;
|
||||
memcpy(&g_now, &now, sizeof(now));
|
||||
}
|
||||
|
||||
long double ConvertTicksToNanos(uint64_t ticks) {
|
||||
if (!g_now.once) Refresh();
|
||||
return ticks * g_now.cpn; /* pico scale */
|
||||
}
|
|
@ -21,6 +21,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/fmt/magnumstrs.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -74,7 +75,8 @@ int openat(int dirfd, const char *file, int flags, ...) {
|
|||
} else {
|
||||
rc = efault();
|
||||
}
|
||||
STRACE("openat(%s, %#s, %#x, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
|
||||
flags, (flags & (O_CREAT | O_TMPFILE)) ? mode : 0, rc);
|
||||
STRACE("openat(%s, %#s, %s, %#o) → %d% m", __strace_dirfd(buf, dirfd), file,
|
||||
DescribeOpenFlags(flags), (flags & (O_CREAT | O_TMPFILE)) ? mode : 0,
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ COSMOPOLITAN_C_START_
|
|||
|
||||
typedef unsigned char u_char;
|
||||
|
||||
int pledge(const char *promises, const char *execpromises);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_COMPAT_OPENBSD_H_ */
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/nt/enum/fileflagandattributes.h"
|
||||
#include "libc/nt/ipc.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/sysv/consts/limits.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
|
@ -42,9 +43,9 @@ textwindows int sys_pipe_nt(int pipefd[2], unsigned flags) {
|
|||
} else {
|
||||
mode = kNtPipeTypeMessage | kNtPipeReadmodeMessage;
|
||||
}
|
||||
if ((hin = CreateNamedPipe(pipename,
|
||||
kNtPipeAccessInbound | kNtFileFlagOverlapped, mode,
|
||||
1, 512, 512, 0, &kNtIsInheritable)) != -1) {
|
||||
if ((hin = CreateNamedPipe(
|
||||
pipename, kNtPipeAccessInbound | kNtFileFlagOverlapped, mode, 1,
|
||||
PIPE_BUF, PIPE_BUF, 0, &kNtIsInheritable)) != -1) {
|
||||
if ((hout = CreateFile(pipename, kNtGenericWrite, 0, &kNtIsInheritable,
|
||||
kNtOpenExisting, kNtFileFlagOverlapped, 0)) != -1) {
|
||||
g_fds.p[reader].kind = kFdFile;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
@ -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)) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -81,7 +81,7 @@ char *realpath(const char *filename, char *resolved)
|
|||
ssize_t rc;
|
||||
int e, up, check_dir=0;
|
||||
size_t k, p, q, l, l0, cnt=0, nup=0;
|
||||
char output[PATH_MAX], stack[PATH_MAX+1], *z;
|
||||
char output[PATH_MAX], stack[PATH_MAX], *z;
|
||||
|
||||
if (!filename) {
|
||||
einval();
|
||||
|
|
|
@ -88,9 +88,9 @@ int __reservefd(int start) {
|
|||
/**
|
||||
* Closes non-stdio file descriptors to free dynamic memory.
|
||||
*/
|
||||
static void __freefds(void) {
|
||||
static void FreeFds(void) {
|
||||
int i;
|
||||
NTTRACE("__freefds()");
|
||||
NTTRACE("FreeFds()");
|
||||
for (i = 3; i < g_fds.n; ++i) {
|
||||
if (g_fds.p[i].kind) {
|
||||
close(i);
|
||||
|
@ -104,10 +104,10 @@ static void __freefds(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static textstartup void __freefds_init(void) {
|
||||
atexit(__freefds);
|
||||
static textstartup void FreeFdsInit(void) {
|
||||
atexit(FreeFds);
|
||||
}
|
||||
|
||||
const void *const __freefds_ctor[] initarray = {
|
||||
__freefds_init,
|
||||
const void *const FreeFdsCtor[] initarray = {
|
||||
FreeFdsInit,
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
if (IsWindows() && gid == getgid()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = sys_setgid(gid);
|
||||
STRACE("%s(%d) → %d% m", "setgid", gid);
|
||||
}
|
||||
STRACE("setgid(%d) → %d% m", gid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
35
libc/calls/setregid.c
Normal file
35
libc/calls/setregid.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
35
libc/calls/setreuid.c
Normal 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;
|
||||
}
|
|
@ -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;
|
||||
if (IsWindows() && uid == getuid()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = sys_setuid(uid);
|
||||
STRACE("%s(%d) → %d% m", "setuid", uid);
|
||||
}
|
||||
STRACE("setuid(%d) → %d% m", uid, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/bits/bits.h"
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/sigbits.h"
|
||||
|
@ -34,6 +35,8 @@
|
|||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/intrin/spinlock.h"
|
||||
#include "libc/limits.h"
|
||||
#include "libc/log/backtrace.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
|
@ -22,13 +22,14 @@
|
|||
/**
|
||||
* Adds signal to set.
|
||||
*
|
||||
* @return true, false, or -1 w/ errno
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raises EINVAL if `1 ≤ sig ≤ NSIG` isn't the case
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int sigaddset(sigset_t *set, int sig) {
|
||||
unsigned i = sig - 1;
|
||||
if (i < sizeof(set->__bits) * 8) {
|
||||
set->__bits[i >> 6] |= 1ull << (i & 63);
|
||||
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
set->__bits[(sig - 1) >> 6] |= 1ull << ((sig - 1) & 63);
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
|
|
21
libc/calls/sigcount.c
Normal file
21
libc/calls/sigcount.c
Normal 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;
|
|
@ -23,12 +23,13 @@
|
|||
* Removes signal from set.
|
||||
*
|
||||
* @return 0 on success, or -1 w/ errno
|
||||
* @raises EINVAL if `1 ≤ sig ≤ NSIG` isn't the case
|
||||
* @asyncsignalsafe
|
||||
*/
|
||||
int sigdelset(sigset_t *set, int sig) {
|
||||
unsigned i = sig - 1;
|
||||
if (i < sizeof(set->__bits) * 8) {
|
||||
set->__bits[i >> 6] &= ~(1ull << (i & 63));
|
||||
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
set->__bits[(sig - 1) >> 6] &= ~(1ull << ((sig - 1) & 63));
|
||||
return 0;
|
||||
} else {
|
||||
return einval();
|
||||
|
|
|
@ -22,14 +22,15 @@
|
|||
/**
|
||||
* Returns true if signal is member of set.
|
||||
*
|
||||
* @return true, false, or -1 w/ errno
|
||||
* @return 1 if set, 0 if not set, or -1 w/ errno
|
||||
* @raises EINVAL if `1 ≤ sig ≤ NSIG` isn't the case
|
||||
* @asyncsignalsafe
|
||||
* @vforksafe
|
||||
*/
|
||||
int sigismember(const sigset_t *set, int sig) {
|
||||
unsigned i = sig - 1;
|
||||
if (i < sizeof(set->__bits) * 8) {
|
||||
return (set->__bits[i >> 6] >> (i & 63)) & 1;
|
||||
_Static_assert(sizeof(set->__bits[0]) * CHAR_BIT == 64, "");
|
||||
if (1 <= sig && sig <= NSIG) {
|
||||
return !!(set->__bits[(sig - 1) >> 6] & (1ull << ((sig - 1) & 63)));
|
||||
} else {
|
||||
return einval();
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
#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 */
|
||||
#define _NTTRACE 0 /* not configurable w/ flag yet */
|
||||
|
||||
#define STRACE_PROLOGUE "%rSYS %5P %'18T "
|
||||
|
||||
|
@ -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
|
||||
|
|
|
@ -10,7 +10,7 @@ struct stat { /* cosmo abi */
|
|||
uint32_t st_mode; /* 24: octal file mask thing */
|
||||
uint32_t st_uid; /* 28: user id of owner */
|
||||
uint32_t st_gid; /* group id of owning group */
|
||||
uint32_t st_flags; /* flags (bsd-only) */
|
||||
uint32_t st_flags; /* nt/xnu/bsd-only */
|
||||
uint64_t st_rdev; /* id of device if a special file */
|
||||
int64_t st_size; /* bytes in file */
|
||||
int64_t st_blksize; /* preferred chunking for underlying filesystem */
|
||||
|
@ -19,7 +19,7 @@ struct stat { /* cosmo abi */
|
|||
struct timespec st_mtim; /* modified time */
|
||||
struct timespec st_ctim; /* complicated time */
|
||||
struct timespec st_birthtim;
|
||||
uint64_t st_gen;
|
||||
uint64_t st_gen; /* xnu/bsd only */
|
||||
};
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
/**
|
||||
* Flushes all open file handles and, if possible, all disk drives.
|
||||
*/
|
||||
int sys_sync_nt(void) {
|
||||
textwindows int sys_sync_nt(void) {
|
||||
unsigned i;
|
||||
int64_t volume;
|
||||
uint32_t drives;
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
* @return previous mask
|
||||
* @note always succeeds
|
||||
*/
|
||||
unsigned umask(unsigned newmask) {
|
||||
unsigned oldmask;
|
||||
int umask(int newmask) {
|
||||
int oldmask;
|
||||
if (!IsWindows()) {
|
||||
oldmask = sys_umask(newmask);
|
||||
} else {
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "libc/dce.h"
|
||||
#include "libc/fmt/itoa.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/nt/enum/computernameformat.h"
|
||||
#include "libc/nt/struct/teb.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
|
94
libc/calls/vdsofunc.greg.c
Normal file
94
libc/calls/vdsofunc.greg.c
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*-*- 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/bits/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/elf/scalar.h"
|
||||
#include "libc/elf/struct/ehdr.h"
|
||||
#include "libc/elf/struct/shdr.h"
|
||||
#include "libc/elf/struct/sym.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sysv/consts/auxv.h"
|
||||
|
||||
#define LAZY_RHEL7_RELOCATION 0xfffff
|
||||
|
||||
#define GetStr(tab, rva) ((char *)(tab) + (rva))
|
||||
#define GetSection(e, s) ((void *)((intptr_t)(e) + (size_t)(s)->sh_offset))
|
||||
#define GetShstrtab(e) GetSection(e, GetShdr(e, (e)->e_shstrndx))
|
||||
#define GetSectionName(e, s) GetStr(GetShstrtab(e), (s)->sh_name)
|
||||
#define GetPhdr(e, i) \
|
||||
((Elf64_Phdr *)((intptr_t)(e) + (e)->e_phoff + \
|
||||
(size_t)(e)->e_phentsize * (i)))
|
||||
#define GetShdr(e, i) \
|
||||
((Elf64_Shdr *)((intptr_t)(e) + (e)->e_shoff + \
|
||||
(size_t)(e)->e_shentsize * (i)))
|
||||
|
||||
static char *GetDynamicStringTable(Elf64_Ehdr *e, size_t *n) {
|
||||
char *name;
|
||||
Elf64_Half i;
|
||||
Elf64_Shdr *shdr;
|
||||
for (i = 0; i < e->e_shnum; ++i) {
|
||||
shdr = GetShdr(e, i);
|
||||
name = GetSectionName(e, GetShdr(e, i));
|
||||
if (shdr->sh_type == SHT_STRTAB) {
|
||||
name = GetSectionName(e, GetShdr(e, i));
|
||||
if (name && READ64LE(name) == READ64LE(".dynstr")) {
|
||||
if (n) *n = shdr->sh_size;
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Elf64_Sym *GetDynamicSymbolTable(Elf64_Ehdr *e, Elf64_Xword *n) {
|
||||
Elf64_Half i;
|
||||
Elf64_Shdr *shdr;
|
||||
for (i = e->e_shnum; i > 0; --i) {
|
||||
shdr = GetShdr(e, i - 1);
|
||||
if (shdr->sh_type == SHT_DYNSYM) {
|
||||
if (shdr->sh_entsize != sizeof(Elf64_Sym)) continue;
|
||||
if (n) *n = shdr->sh_size / shdr->sh_entsize;
|
||||
return GetSection(e, shdr);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Linux Kernel Virtual Dynamic Shared Object function address.
|
||||
*/
|
||||
void *__vdsofunc(const char *name) {
|
||||
size_t m;
|
||||
char *names;
|
||||
Elf64_Ehdr *ehdr;
|
||||
Elf64_Xword i, n;
|
||||
Elf64_Sym *symtab, *sym;
|
||||
if ((ehdr = (Elf64_Ehdr *)getauxval(AT_SYSINFO_EHDR)) &&
|
||||
(names = GetDynamicStringTable(ehdr, &m)) &&
|
||||
(symtab = GetDynamicSymbolTable(ehdr, &n))) {
|
||||
for (i = 0; i < n; ++i) {
|
||||
if (!__strcmp(names + symtab[i].st_name, name)) {
|
||||
return (char *)ehdr + (symtab[i].st_value & LAZY_RHEL7_RELOCATION);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -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());
|
||||
|
|
|
@ -48,6 +48,26 @@ typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
|||
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||
|
||||
#define TIME_T_MAX __INT64_MAX__
|
||||
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||
|
||||
#define TIME_T_MIN (-TIME_T_MAX - 1)
|
||||
#define UINT_FAST64_MIN (-UINT_FAST64_MAX - 1)
|
||||
#define UINT_FAST8_MIN (-UINT_FAST8_MAX - 1)
|
||||
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||
#define UINT_FAST32_MIN (-UINT_FAST32_MAX - 1)
|
||||
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||
#define UINT_FAST16_MIN (-UINT_FAST16_MAX - 1)
|
||||
|
||||
#define atomic_bool _Atomic(_Bool)
|
||||
#define atomic_bool32 atomic_int_fast32_t
|
||||
#define atomic_char _Atomic(char)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -82,6 +82,39 @@ complex long double clogl(complex long double);
|
|||
complex long double conjl(complex long double);
|
||||
complex long double cpowl(complex long double, complex long double);
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define __CIMAG(x, t) \
|
||||
(+(union { \
|
||||
_Complex t __z; \
|
||||
t __xy[2]; \
|
||||
}){(_Complex t)(x)} \
|
||||
.__xy[1])
|
||||
#define creal(x) ((double)(x))
|
||||
#define crealf(x) ((float)(x))
|
||||
#define creall(x) ((long double)(x))
|
||||
#define cimag(x) __CIMAG(x, double)
|
||||
#define cimagf(x) __CIMAG(x, float)
|
||||
#define cimagl(x) __CIMAG(x, long double)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define _Complex_I (__extension__(0.0f + 1.0fi))
|
||||
#else
|
||||
#define _Complex_I (0.0f + 1.0fi)
|
||||
#endif
|
||||
|
||||
#ifdef _Imaginary_I
|
||||
#define __CMPLX(x, y, t) ((t)(x) + _Imaginary_I * (t)(y))
|
||||
#elif defined(__clang__)
|
||||
#define __CMPLX(x, y, t) (+(_Complex t){(t)(x), (t)(y)})
|
||||
#else
|
||||
#define __CMPLX(x, y, t) (__builtin_complex((t)(x), (t)(y)))
|
||||
#endif
|
||||
|
||||
#define CMPLX(x, y) __CMPLX(x, y, double)
|
||||
#define CMPLXF(x, y) __CMPLX(x, y, float)
|
||||
#define CMPLXL(x, y) __CMPLX(x, y, long double)
|
||||
|
||||
#endif /* C11 */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -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];
|
||||
char *name, *number, *alias, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/protocols";
|
||||
|
|
|
@ -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];
|
||||
char *name, *number, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/protocols";
|
||||
|
|
|
@ -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];
|
||||
char *name, *port, *proto, *alias, *comment, *tok;
|
||||
if (!(path = filepath)) {
|
||||
path = "/etc/services";
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue