mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-03-06 00:46:23 +00:00
Make improvements
- This commit mints a new release of APE Loader v1.2 which supports loading ELF programs with a non-contiguous virtual address layout even though we've never been able to take advantage of it, due to how `objcopy -SO binary` fills any holes left by PT_LOAD. This'll change soon, since we'll have a new way of creating APE binaries. - The undiamonding trick with our ioctl() implementation is removed since POSIX has been killing ioctl() for years and they've done a much better job. One problem it resolves, is that ioctl(FIONREAD) wasn't working earlier and that caused issues when building Emacs
This commit is contained in:
parent
a1b1fdd1a4
commit
1ee2e89326
53 changed files with 1155 additions and 1255 deletions
20
ape/ape.mk
20
ape/ape.mk
|
@ -197,25 +197,25 @@ o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
|||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: private \
|
||||
LDFLAGS += \
|
||||
-z common-page-size=0x10 \
|
||||
-z max-page-size=0x10
|
||||
APE_LOADER_LDFLAGS = \
|
||||
-static \
|
||||
-no-pie \
|
||||
-nostdlib \
|
||||
--no-dynamic-linker \
|
||||
-zcommon-page-size=0x1000 \
|
||||
-zmax-page-size=0x1000
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/loader-elf.o \
|
||||
ape/loader.lds
|
||||
@$(ELFLINK)
|
||||
@$(COMPILE) -ALINK.elf $(LINK) -T ape/loader.lds $(APE_LOADER_LDFLAGS) -o $@ o/$(MODE)/ape/loader-elf.o o/$(MODE)/ape/loader.o
|
||||
|
||||
o/$(MODE)/ape/ape.macho.dbg: private \
|
||||
LDFLAGS += \
|
||||
-z common-page-size=0x10 \
|
||||
-z max-page-size=0x10
|
||||
o/$(MODE)/ape/ape.macho.dbg: \
|
||||
o/$(MODE)/ape/loader-xnu.o \
|
||||
o/$(MODE)/ape/loader-macho.o \
|
||||
ape/loader.lds
|
||||
@$(ELFLINK)
|
||||
@$(COMPILE) -ALINK.elf $(LINK) -T ape/loader.lds $(APE_LOADER_LDFLAGS) -o $@ o/$(MODE)/ape/loader-macho.o o/$(MODE)/ape/loader-xnu.o
|
||||
|
||||
.PHONY: o/$(MODE)/ape
|
||||
o/$(MODE)/ape: $(APE_CHECKS) \
|
||||
|
|
|
@ -12,13 +12,8 @@ echo "Author: Justine Tunney <jtunney@gmail.com>" >&2
|
|||
################################################################################
|
||||
# INSTALL APE LOADER SYSTEMWIDE
|
||||
|
||||
if [ -f o/depend ]; then
|
||||
# mkdeps.com build was successfully run so assume we can build
|
||||
echo >&2
|
||||
echo "recompiling ape loader" >&2
|
||||
echo "running: make -j8 o//ape" >&2
|
||||
make -j8 o//ape || exit
|
||||
echo "done" >&2
|
||||
if [ -f o/depend ] && make -j8 o//ape; then
|
||||
echo "successfully recompiled ape loader" >&2
|
||||
elif [ -d build/bootstrap ]; then
|
||||
# if make isn't being used then it's unlikely the user changed the sources
|
||||
# in that case the prebuilt binaries should be completely up-to-date
|
||||
|
|
250
ape/loader.c
250
ape/loader.c
|
@ -77,12 +77,18 @@
|
|||
* @note this can probably be used as a binfmt_misc interpreter
|
||||
*/
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
#define NULL_PAGE 2097152
|
||||
|
||||
#define LINUX 1
|
||||
#define XNU 8
|
||||
#define OPENBSD 16
|
||||
#define FREEBSD 32
|
||||
#define NETBSD 64
|
||||
|
||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||
|
||||
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
||||
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||
|
@ -103,29 +109,29 @@
|
|||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define ET_EXEC 2
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
#define X_OK 1
|
||||
#define XCR0_SSE 2
|
||||
#define XCR0_AVX 4
|
||||
#define PR_SET_MM 35
|
||||
#define PR_SET_MM_EXE_FILE 13
|
||||
|
||||
#define Min(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||
#define Roundup(X, K) (((X) + (K)-1) & -(K))
|
||||
#define Rounddown(X, K) ((X) & -(K))
|
||||
|
||||
#define Read32(S) \
|
||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
|
||||
|
@ -190,16 +196,14 @@ struct ApeLoader {
|
|||
union ElfEhdrBuf ehdr;
|
||||
union ElfPhdrBuf phdr;
|
||||
struct PathSearcher ps;
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
long SystemCall(long arg1, //
|
||||
long arg2, //
|
||||
long arg3, //
|
||||
long arg4, //
|
||||
long arg5, //
|
||||
long arg6, //
|
||||
long arg7, //
|
||||
long magi);
|
||||
long SystemCall(long arg1, long arg2, long arg3, long arg4, long arg5,
|
||||
long arg6, long arg7, long magi);
|
||||
|
||||
extern char __executable_start[];
|
||||
extern char _end[];
|
||||
|
||||
static int ToLower(int c) {
|
||||
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
||||
|
@ -300,7 +304,7 @@ static long Pread(int fd, void *data, unsigned long size, long off, int os) {
|
|||
} else if (IsFreebsd()) {
|
||||
magi = 0x1db;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 0x0a9; // OpenBSD v7.3+
|
||||
magi = 0x0a9; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 0x0ad;
|
||||
} else {
|
||||
|
@ -337,6 +341,11 @@ static int Open(const char *path, int flags, int mode, int os) {
|
|||
(IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0));
|
||||
}
|
||||
|
||||
static int Mprotect(void *addr, unsigned long size, int prot, int os) {
|
||||
return SystemCall((long)addr, size, prot, 0, 0, 0, 0,
|
||||
(IsLinux() ? 10 : 74) | (IsXnu() ? 0x2000000 : 0));
|
||||
}
|
||||
|
||||
static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
|
||||
long off, int os) {
|
||||
long magi;
|
||||
|
@ -347,7 +356,7 @@ static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
|
|||
} else if (IsFreebsd()) {
|
||||
magi = 477;
|
||||
} else if (IsOpenbsd()) {
|
||||
magi = 49; // OpenBSD v7.3+
|
||||
magi = 49; /* OpenBSD v7.3+ */
|
||||
} else if (IsNetbsd()) {
|
||||
magi = 197;
|
||||
} else {
|
||||
|
@ -480,15 +489,26 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
|||
long *sp, struct ElfEhdr *e,
|
||||
struct ElfPhdr *p) {
|
||||
long rc;
|
||||
int prot, flags;
|
||||
int prot;
|
||||
int flags;
|
||||
int found_code;
|
||||
int found_entry;
|
||||
long code, codesize;
|
||||
unsigned long a, b, i;
|
||||
unsigned long a, b, c, d, i, j;
|
||||
|
||||
/* load elf */
|
||||
code = 0;
|
||||
codesize = 0;
|
||||
for (i = e->e_phnum; i--;) {
|
||||
found_code = 0;
|
||||
found_entry = 0;
|
||||
for (i = 0; i < e->e_phnum; ++i) {
|
||||
|
||||
/* validate program header */
|
||||
if (p[i].p_type == PT_INTERP) {
|
||||
Pexit(os, exe, 0, "ELF has PT_INTERP which is unsupported");
|
||||
}
|
||||
if (p[i].p_type == PT_DYNAMIC) {
|
||||
Pexit(os, exe, 0, "not a static executable");
|
||||
Pexit(os, exe, 0, "ELF has PT_DYNAMIC which is unsupported");
|
||||
}
|
||||
if (p[i].p_type != PT_LOAD) {
|
||||
continue;
|
||||
|
@ -496,12 +516,39 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
|||
if (!p[i].p_memsz) {
|
||||
continue;
|
||||
}
|
||||
if (p[i].p_vaddr & 4095) {
|
||||
Pexit(os, exe, 0, "APE phdr addr must be 4096-aligned");
|
||||
if (p[i].p_filesz > p[i].p_memsz) {
|
||||
Pexit(os, exe, 0, "ELF phdr filesz exceeds memsz");
|
||||
}
|
||||
if (p[i].p_offset & 4095) {
|
||||
Pexit(os, exe, 0, "APE phdr offset must be 4096-aligned");
|
||||
if ((p[i].p_vaddr & (PAGE_SIZE - 1)) != (p[i].p_offset & (PAGE_SIZE - 1))) {
|
||||
Pexit(os, exe, 0, "ELF phdr virt/off skew mismatch w.r.t. pagesize");
|
||||
}
|
||||
if (p[i].p_vaddr + p[i].p_memsz < p[i].p_vaddr ||
|
||||
p[i].p_vaddr + p[i].p_memsz + (PAGE_SIZE - 1) < p[i].p_vaddr) {
|
||||
Pexit(os, exe, 0, "ELF phdr vaddr+memsz overflow");
|
||||
}
|
||||
if (p[i].p_vaddr + p[i].p_filesz < p[i].p_vaddr ||
|
||||
p[i].p_vaddr + p[i].p_filesz + (PAGE_SIZE - 1) < p[i].p_vaddr) {
|
||||
Pexit(os, exe, 0, "ELF phdr vaddr+files overflow");
|
||||
}
|
||||
a = p[i].p_vaddr & -PAGE_SIZE;
|
||||
b = (p[i].p_vaddr + p[i].p_memsz + (PAGE_SIZE - 1)) & -PAGE_SIZE;
|
||||
if (MAX(a, 0) < MIN(b, NULL_PAGE)) {
|
||||
Pexit(os, exe, 0, "ELF overlaps NULL page");
|
||||
}
|
||||
if (MAX(a, (unsigned long)__executable_start) <
|
||||
MIN(b, (unsigned long)_end)) {
|
||||
Pexit(os, exe, 0, "ELF overlaps your APE loader");
|
||||
}
|
||||
for (j = i + 1; j < e->e_phnum; ++j) {
|
||||
if (p[j].p_type != PT_LOAD) continue;
|
||||
c = p[j].p_vaddr & -PAGE_SIZE;
|
||||
d = (p[j].p_vaddr + p[j].p_memsz + (PAGE_SIZE - 1)) & -PAGE_SIZE;
|
||||
if (MAX(a, c) < MIN(b, d)) {
|
||||
Pexit(os, exe, 0, "ELF overlaps its own vaspace");
|
||||
}
|
||||
}
|
||||
|
||||
/* configure mapping */
|
||||
prot = 0;
|
||||
flags = MAP_FIXED | MAP_PRIVATE;
|
||||
if (p[i].p_flags & PF_R) {
|
||||
|
@ -512,47 +559,76 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
|||
}
|
||||
if (p[i].p_flags & PF_X) {
|
||||
prot |= PROT_EXEC;
|
||||
code = p[i].p_vaddr;
|
||||
codesize = p[i].p_filesz;
|
||||
if (!found_code) {
|
||||
code = p[i].p_vaddr;
|
||||
codesize = p[i].p_filesz;
|
||||
}
|
||||
if (p[i].p_vaddr <= e->e_entry &&
|
||||
e->e_entry < p[i].p_vaddr + p[i].p_memsz) {
|
||||
found_entry = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* load from file */
|
||||
if (p[i].p_filesz) {
|
||||
if ((rc = Mmap((void *)p[i].p_vaddr, p[i].p_filesz, prot, flags, fd,
|
||||
p[i].p_offset, os)) < 0) {
|
||||
Pexit(os, exe, rc, "image mmap");
|
||||
void *addr;
|
||||
unsigned long size;
|
||||
int dirty, prot1, prot2;
|
||||
dirty = 0;
|
||||
prot1 = prot;
|
||||
prot2 = prot;
|
||||
a = p[i].p_vaddr + p[i].p_filesz;
|
||||
b = (a + (PAGE_SIZE - 1)) & -PAGE_SIZE;
|
||||
c = p[i].p_vaddr + p[i].p_memsz;
|
||||
if (b > c) b = c;
|
||||
if (c > b) {
|
||||
dirty = 1;
|
||||
if (~prot1 & PROT_WRITE) {
|
||||
prot1 = PROT_READ | PROT_WRITE;
|
||||
}
|
||||
}
|
||||
if ((a = Min(-p[i].p_filesz & 4095, p[i].p_memsz - p[i].p_filesz))) {
|
||||
MemSet((void *)(p[i].p_vaddr + p[i].p_filesz), 0, a);
|
||||
addr = (void *)(p[i].p_vaddr & -PAGE_SIZE);
|
||||
size = (p[i].p_vaddr & (PAGE_SIZE - 1)) + p[i].p_filesz;
|
||||
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -PAGE_SIZE, os);
|
||||
if (rc < 0) Pexit(os, exe, rc, "prog mmap");
|
||||
if (dirty) MemSet((void *)a, 0, b - a);
|
||||
if (prot2 != prot1) {
|
||||
rc = Mprotect(addr, size, prot2, os);
|
||||
if (rc < 0) Pexit(os, exe, rc, "prog mprotect");
|
||||
}
|
||||
}
|
||||
if ((b = Roundup(p[i].p_memsz, 4096)) >
|
||||
(a = Roundup(p[i].p_filesz, 4096))) {
|
||||
if ((rc = Mmap((void *)p[i].p_vaddr + a, b - a, prot,
|
||||
flags | MAP_ANONYMOUS, -1, 0, os)) < 0) {
|
||||
Pexit(os, exe, rc, "bss mmap");
|
||||
}
|
||||
|
||||
/* allocate extra bss */
|
||||
a = p[i].p_vaddr + p[i].p_filesz;
|
||||
a = (a + (PAGE_SIZE - 1)) & -PAGE_SIZE;
|
||||
b = p[i].p_vaddr + p[i].p_memsz;
|
||||
if (b > a) {
|
||||
rc = Mmap((void *)a, b - a, prot, flags | MAP_ANONYMOUS, 0, 0, os);
|
||||
if (rc < 0) Pexit(os, exe, rc, "bss mmap");
|
||||
}
|
||||
}
|
||||
if (!code) {
|
||||
Pexit(os, exe, 0, "ELF needs PT_LOAD phdr w/ PF_X");
|
||||
}
|
||||
|
||||
/* finish up */
|
||||
if (!found_entry) {
|
||||
Pexit(os, exe, 0, "ELF entrypoint not found in PT_LOAD with PF_X");
|
||||
}
|
||||
Close(fd, os);
|
||||
Msyscall(code, codesize, os);
|
||||
|
||||
// we clear all the general registers we can to have some wiggle room
|
||||
// to extend the behavior of this loader in the future. we don't need
|
||||
// to clear the xmm registers since the ape loader should be compiled
|
||||
// with the -mgeneral-regs-only flag.
|
||||
/* we clear all the general registers we can to have some wiggle room
|
||||
to extend the behavior of this loader in the future. we don't need
|
||||
to clear the xmm registers since the ape loader should be compiled
|
||||
with the -mgeneral-regs-only flag. */
|
||||
asm volatile("xor\t%%eax,%%eax\n\t"
|
||||
"xor\t%%r8d,%%r8d\n\t"
|
||||
"xor\t%%r9d,%%r9d\n\t"
|
||||
"xor\t%%r10d,%%r10d\n\t"
|
||||
"xor\t%%r11d,%%r11d\n\t"
|
||||
"xor\t%%ebx,%%ebx\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r12d,%%r12d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r13d,%%r13d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r14d,%%r14d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%r15d,%%r15d\n\t" // netbsd doesnt't clear this
|
||||
"xor\t%%ebx,%%ebx\n\t" /* netbsd doesnt't clear this */
|
||||
"xor\t%%r12d,%%r12d\n\t" /* netbsd doesnt't clear this */
|
||||
"xor\t%%r13d,%%r13d\n\t" /* netbsd doesnt't clear this */
|
||||
"xor\t%%r14d,%%r14d\n\t" /* netbsd doesnt't clear this */
|
||||
"xor\t%%r15d,%%r15d\n\t" /* netbsd doesnt't clear this */
|
||||
"mov\t%%rdx,%%rsp\n\t"
|
||||
"xor\t%%edx,%%edx\n\t"
|
||||
"push\t%%rsi\n\t"
|
||||
|
@ -566,16 +642,30 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
|||
}
|
||||
|
||||
static void TryElf(struct ApeLoader *M, const char *exe, int fd, long *sp,
|
||||
int os) {
|
||||
unsigned size;
|
||||
if (Read32(M->ehdr.buf) == Read32("\177ELF") && //
|
||||
M->ehdr.ehdr.e_type == ET_EXEC && //
|
||||
M->ehdr.ehdr.e_machine == EM_NEXGEN32E && //
|
||||
M->ehdr.ehdr.e_ident[EI_CLASS] != ELFCLASS32 && //
|
||||
M->ehdr.ehdr.e_phentsize >= sizeof(M->phdr.phdr) && //
|
||||
(size = (unsigned)M->ehdr.ehdr.e_phnum * M->ehdr.ehdr.e_phentsize) <=
|
||||
sizeof(M->phdr.buf) &&
|
||||
long *auxv, int os) {
|
||||
unsigned size = M->ehdr.ehdr.e_phnum;
|
||||
if (Read32(M->ehdr.buf) == Read32("\177ELF") &&
|
||||
M->ehdr.ehdr.e_type == ET_EXEC &&
|
||||
M->ehdr.ehdr.e_machine == EM_NEXGEN32E &&
|
||||
M->ehdr.ehdr.e_ident[EI_CLASS] != ELFCLASS32 &&
|
||||
M->ehdr.ehdr.e_phentsize >= sizeof(M->phdr.phdr) &&
|
||||
(size *= M->ehdr.ehdr.e_phentsize) <= sizeof(M->phdr.buf) &&
|
||||
Pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff, os) == size) {
|
||||
for (; *auxv; auxv += 2) {
|
||||
switch (*auxv) {
|
||||
case AT_PHDR:
|
||||
auxv[1] = (unsigned long)&M->phdr;
|
||||
break;
|
||||
case AT_PHENT:
|
||||
auxv[1] = M->ehdr.ehdr.e_phentsize;
|
||||
break;
|
||||
case AT_PHNUM:
|
||||
auxv[1] = M->ehdr.ehdr.e_phnum;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Spawn(os, exe, fd, sp, &M->ehdr.ehdr, &M->phdr.phdr);
|
||||
}
|
||||
}
|
||||
|
@ -588,7 +678,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
long *auxv, *ap, *ew;
|
||||
char *p, *exe, *prog, **argv, **envp;
|
||||
|
||||
// detect freebsd
|
||||
/* detect freebsd */
|
||||
if (SupportsXnu() && dl == XNU) {
|
||||
os = XNU;
|
||||
} else if (SupportsFreebsd() && di) {
|
||||
|
@ -598,7 +688,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
os = 0;
|
||||
}
|
||||
|
||||
// extract arguments
|
||||
/* extract arguments */
|
||||
argc = *sp;
|
||||
argv = (char **)(sp + 1);
|
||||
envp = (char **)(sp + 1 + argc + 1);
|
||||
|
@ -609,12 +699,12 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
}
|
||||
}
|
||||
|
||||
// detect openbsd
|
||||
/* detect openbsd */
|
||||
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
||||
os = OPENBSD;
|
||||
}
|
||||
|
||||
// detect netbsd and find end of words
|
||||
/* detect netbsd and find end of words */
|
||||
for (ap = auxv; ap[0]; ap += 2) {
|
||||
if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
|
||||
os = NETBSD;
|
||||
|
@ -622,23 +712,23 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
}
|
||||
ew = ap + 1;
|
||||
|
||||
// allocate loader memory
|
||||
/* allocate loader memory */
|
||||
n = sizeof(*M) / sizeof(long);
|
||||
MemMove(sp - n, sp, (char *)ew - (char *)sp);
|
||||
sp -= n, argv -= n, envp -= n, auxv -= n;
|
||||
M = (struct ApeLoader *)(ew - n);
|
||||
|
||||
// default operating system
|
||||
/* default operating system */
|
||||
if (!os) {
|
||||
os = LINUX;
|
||||
}
|
||||
|
||||
// we can load via shell, shebang, or binfmt_misc
|
||||
/* we can load via shell, shebang, or binfmt_misc */
|
||||
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
||||
// if the first argument is a hyphen then we give the user the
|
||||
// power to change argv[0] or omit it entirely. most operating
|
||||
// systems don't permit the omission of argv[0] but we do, b/c
|
||||
// it's specified by ANSI X3.159-1988.
|
||||
/* if the first argument is a hyphen then we give the user the
|
||||
power to change argv[0] or omit it entirely. most operating
|
||||
systems don't permit the omission of argv[0] but we do, b/c
|
||||
it's specified by ANSI X3.159-1988. */
|
||||
prog = (char *)sp[3];
|
||||
argc = sp[3] = sp[0] - 3;
|
||||
argv = (char **)((sp += 3) + 1);
|
||||
|
@ -646,7 +736,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
Print(os, 2,
|
||||
"usage: ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
"αcτµαlly pδrταblε εxεcµταblε loader v1.1\n"
|
||||
"αcτµαlly pδrταblε εxεcµταblε loader v1.2\n"
|
||||
"copyright 2022 justine alexandra roberts tunney\n"
|
||||
"https://justine.lol/ape.html\n",
|
||||
0l);
|
||||
|
@ -657,7 +747,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
argv = (char **)((sp += 1) + 1);
|
||||
}
|
||||
|
||||
// resolve path of executable and read its first page
|
||||
/* resolve path of executable and read its first page */
|
||||
if (!(exe = Commandv(&M->ps, os, prog, GetEnv(envp, "PATH")))) {
|
||||
Pexit(os, prog, 0, "not found (maybe chmod +x)");
|
||||
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||
|
@ -668,17 +758,17 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
Pexit(os, exe, 0, "too small");
|
||||
}
|
||||
|
||||
// change argv[0] to resolved path if it's ambiguous
|
||||
/* change argv[0] to resolved path if it's ambiguous */
|
||||
if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
|
||||
argv[0] = exe;
|
||||
}
|
||||
|
||||
// ape intended behavior
|
||||
// 1. if file is a native executable, try to run it natively
|
||||
// 2. if ape, will scan shell script for elf printf statements
|
||||
// 3. shell script may have multiple lines producing elf headers
|
||||
// 4. all elf printf lines must exist in the first 4096 bytes of file
|
||||
// 5. elf program headers may appear anywhere in the binary
|
||||
/* ape intended behavior
|
||||
1. if file is a native executable, try to run it natively
|
||||
2. if ape, will scan shell script for elf printf statements
|
||||
3. shell script may have multiple lines producing elf headers
|
||||
4. all elf printf lines must exist in the first 4096 bytes of file
|
||||
5. elf program headers may appear anywhere in the binary */
|
||||
if ((IsXnu() && Read32(M->ehdr.buf) == 0xFEEDFACE + 1) ||
|
||||
(!IsXnu() && Read32(M->ehdr.buf) == Read32("\177ELF"))) {
|
||||
Close(fd, os);
|
||||
|
@ -708,10 +798,10 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
|
|||
M->ehdr.buf[i++] = c;
|
||||
}
|
||||
if (i >= sizeof(M->ehdr.ehdr)) {
|
||||
TryElf(M, exe, fd, sp, os);
|
||||
TryElf(M, exe, fd, sp, auxv, os);
|
||||
}
|
||||
}
|
||||
}
|
||||
TryElf(M, exe, fd, sp, os);
|
||||
TryElf(M, exe, fd, sp, auxv, os);
|
||||
Pexit(os, exe, 0, "Not an acceptable APE/ELF executable for x86-64");
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@
|
|||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
. = 0x7fff0000;
|
||||
__executable_start = .;
|
||||
.rodata : {
|
||||
KEEP(*(.head))
|
||||
*(.rodata .rodata.*)
|
||||
|
@ -29,6 +30,7 @@ SECTIONS {
|
|||
text = .;
|
||||
*(.text)
|
||||
}
|
||||
_end = .;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -8,7 +8,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
│ SUCH DAMAGE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
#endif
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/errno.h"
|
||||
|
|
|
@ -114,6 +114,7 @@ int getpriority(int, unsigned);
|
|||
int getresgid(unsigned *, unsigned *, unsigned *);
|
||||
int getresuid(unsigned *, unsigned *, unsigned *);
|
||||
int getsid(int) nosideeffect libcesque;
|
||||
int ioctl(int, unsigned long, ...);
|
||||
int ioprio_get(int, int);
|
||||
int ioprio_set(int, int, int);
|
||||
int issetugid(void);
|
||||
|
|
|
@ -136,8 +136,6 @@ o/$(MODE)/libc/calls/mkntenvblock.o: private \
|
|||
|
||||
# we must segregate codegen because:
|
||||
# file contains multiple independently linkable apis
|
||||
o/$(MODE)/libc/calls/ioctl-siocgifconf.o \
|
||||
o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: private \
|
||||
COPTS += \
|
||||
-ffunction-sections \
|
||||
-fdata-sections
|
||||
|
@ -146,14 +144,7 @@ o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: private \
|
|||
# va_arg codegen is very bloated in default mode
|
||||
o//libc/calls/open.o \
|
||||
o//libc/calls/openat.o \
|
||||
o//libc/calls/prctl.o \
|
||||
o//libc/calls/ioctl.o \
|
||||
o//libc/calls/ioctl_default.o \
|
||||
o//libc/calls/ioctl_fioclex-nt.o \
|
||||
o//libc/calls/ioctl_fioclex.o \
|
||||
o//libc/calls/ioctl_siocgifconf-nt.o \
|
||||
o//libc/calls/ioctl_siocgifconf.o \
|
||||
o//libc/calls/fcntl.o: private \
|
||||
o//libc/calls/prctl.o: \
|
||||
CFLAGS += \
|
||||
-Os
|
||||
|
||||
|
|
|
@ -16,27 +16,686 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifdef __STRICT_ANSI__
|
||||
#undef __STRICT_ANSI__
|
||||
#endif
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/iphlpapi.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/ipadapteraddresses.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/iff.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
#define EQUAL(X, Y) ((X) == (Y))
|
||||
/* Maximum number of unicast addresses handled for each interface */
|
||||
#define MAX_UNICAST_ADDR 32
|
||||
#define MAX_NAME_CLASH ((int)('z' - 'a')) /* Allow a..z */
|
||||
|
||||
static struct HostAdapterInfoNode {
|
||||
struct HostAdapterInfoNode *next;
|
||||
char name[IFNAMSIZ]; /* Obtained from FriendlyName */
|
||||
struct sockaddr unicast;
|
||||
struct sockaddr netmask;
|
||||
struct sockaddr broadcast;
|
||||
short flags;
|
||||
} * __hostInfo;
|
||||
|
||||
static int ioctl_default(int fd, unsigned long request, ...) {
|
||||
int rc;
|
||||
void *arg;
|
||||
va_list va;
|
||||
int64_t handle;
|
||||
va_start(va, request);
|
||||
arg = va_arg(va, void *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, request, arg);
|
||||
} else if (__isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdSocket) {
|
||||
handle = __getfdhandleactual(fd);
|
||||
if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
|
||||
return rc;
|
||||
} else {
|
||||
return _weaken(__winsockerr)();
|
||||
}
|
||||
} else {
|
||||
return eopnotsupp();
|
||||
}
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
||||
|
||||
/* Frees all the nodes of the _hostInfo */
|
||||
static textwindows void freeHostInfo(void) {
|
||||
struct HostAdapterInfoNode *next, *node = __hostInfo;
|
||||
if (_weaken(free)) {
|
||||
while (node) {
|
||||
next = node->next;
|
||||
_weaken(free)(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
__hostInfo = NULL;
|
||||
}
|
||||
|
||||
/* Given a short adapter name, look into __hostInfo to see if there is
|
||||
* an adapter with the same name. Returns the pointer to the HostAdapterInfoNode
|
||||
* if found, or NULL if not found
|
||||
*/
|
||||
static textwindows struct HostAdapterInfoNode *findAdapterByName(
|
||||
const char *name) {
|
||||
struct HostAdapterInfoNode *node = __hostInfo;
|
||||
while (node) {
|
||||
if (!strncmp(name, node->name, IFNAMSIZ)) {
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Creates a new HostAdapterInfoNode object, initializes it from
|
||||
* the given adapter, unicast address and address prefixes
|
||||
* and insert it in the __hostInfo.
|
||||
* Increments the pointers to the unicast addresses and
|
||||
* the address prefixes
|
||||
* Returns NULL if an error occurred or the newly created
|
||||
* HostAdapterInfoNode object (last in the list)
|
||||
*/
|
||||
static textwindows struct HostAdapterInfoNode *appendHostInfo(
|
||||
struct HostAdapterInfoNode *parentInfoNode,
|
||||
const char *baseName, /* Max length = IFNAMSIZ-1 */
|
||||
const struct NtIpAdapterAddresses
|
||||
*aa, /* Top level adapter object being processed */
|
||||
struct NtIpAdapterUnicastAddress *
|
||||
*ptrUA, /* Ptr to ptr to unicast address list node */
|
||||
struct NtIpAdapterPrefix *
|
||||
*ptrAP, /* Ptr to ptr to Adapter prefix list node */
|
||||
int count) { /* count is used to create a unique name in case of alias */
|
||||
|
||||
struct HostAdapterInfoNode *temp;
|
||||
struct HostAdapterInfoNode *node;
|
||||
uint32_t ip, netmask, broadcast;
|
||||
struct sockaddr_in *a;
|
||||
int attemptNum;
|
||||
|
||||
if (!_weaken(calloc) || !(node = _weaken(calloc)(1, sizeof(*node)))) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(node->name, baseName, IFNAMSIZ);
|
||||
|
||||
/* Are there more than a single unicast address ? */
|
||||
if (count > 0 || ((*ptrUA)->Next != NULL)) {
|
||||
/* Yes, compose it using <baseName>:<count> */
|
||||
size_t nameLen = strlen(node->name);
|
||||
if (nameLen + 2 > IFNAMSIZ - 2) {
|
||||
/* Appending the ":x" will exceed the size, need to chop the end */
|
||||
nameLen -= 2;
|
||||
}
|
||||
node->name[nameLen - 2] = ':';
|
||||
node->name[nameLen - 1] = '0' + count;
|
||||
node->name[nameLen] = '\0';
|
||||
}
|
||||
|
||||
/* Is there a name clash with other interfaces? */
|
||||
for (attemptNum = 0; attemptNum < MAX_NAME_CLASH; ++attemptNum) {
|
||||
temp = findAdapterByName(node->name);
|
||||
if (!temp) {
|
||||
break;
|
||||
} else {
|
||||
/* Yes, this name has been already used, append an extra
|
||||
* character to resolve conflict. Note since the max length
|
||||
* of the string now is IFNAMSIZ-2, we have just enough space for this.
|
||||
* E.g. 'Ethernet_1' -> 'Ethernet_1a'
|
||||
*/
|
||||
size_t pos = strlen(node->name);
|
||||
node->name[pos] = 'a' + attemptNum;
|
||||
node->name[pos + 1] = '\0';
|
||||
/* Try again */
|
||||
}
|
||||
}
|
||||
|
||||
if (attemptNum == MAX_NAME_CLASH) {
|
||||
/* Cannot resolve the conflict */
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(node);
|
||||
}
|
||||
errno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finally we got a unique short and friendly name */
|
||||
node->unicast = *((*ptrUA)->Address.lpSockaddr);
|
||||
if (*ptrUA == aa->FirstUnicastAddress) {
|
||||
short flags;
|
||||
/* This is the first unicast address of this interface
|
||||
* calculate the flags for this adapter. Flags to consider:
|
||||
* IFF_UP
|
||||
* IFF_BROADCAST ** TODO: We need to validate
|
||||
* IFF_LOOPBACK
|
||||
* IFF_POINTOPOINT
|
||||
* IFF_MULTICAST
|
||||
* IFF_RUNNING ** Same as IFF_UP for now
|
||||
* IFF_PROMISC ** NOT SUPPORTED, unknown how to retrieve it
|
||||
*/
|
||||
flags = 0;
|
||||
if (aa->OperStatus == kNtIfOperStatusUp) flags |= IFF_UP | IFF_RUNNING;
|
||||
if (aa->IfType == kNtIfTypePpp) flags |= IFF_POINTOPOINT;
|
||||
if (!(aa->Flags & kNtIpAdapterNoMulticast)) flags |= IFF_MULTICAST;
|
||||
if (aa->IfType == kNtIfTypeSoftwareLoopback) flags |= IFF_LOOPBACK;
|
||||
if (aa->FirstPrefix) flags |= IFF_BROADCAST;
|
||||
node->flags = flags;
|
||||
} else {
|
||||
/* Copy from previous node */
|
||||
node->flags = parentInfoNode->flags;
|
||||
}
|
||||
|
||||
ip = ntohl(
|
||||
((struct sockaddr_in *)(*ptrUA)->Address.lpSockaddr)->sin_addr.s_addr);
|
||||
netmask = (uint32_t)-1 << (32 - (*ptrUA)->OnLinkPrefixLength);
|
||||
broadcast = (ip & netmask) | (~netmask & -1);
|
||||
|
||||
a = (struct sockaddr_in *)&node->netmask;
|
||||
a->sin_family = AF_INET;
|
||||
a->sin_addr.s_addr = htonl(netmask);
|
||||
|
||||
a = (struct sockaddr_in *)&node->broadcast;
|
||||
a->sin_family = AF_INET;
|
||||
a->sin_addr.s_addr = htonl(broadcast);
|
||||
|
||||
/* Process the prefix and extract the netmask and broadcast */
|
||||
/* According to the doc:
|
||||
*
|
||||
* On Windows Vista and later, the linked IP_ADAPTER_PREFIX
|
||||
* structures pointed to by the FirstPrefix member include three
|
||||
* IP adapter prefixes for each IP address assigned to the
|
||||
* adapter. These include the host IP address prefix, the subnet
|
||||
* IP address prefix, and the subnet broadcast IP address prefix.
|
||||
* In addition, for each adapter there is a multicast address
|
||||
* prefix and a broadcast address prefix.
|
||||
* -Source: MSDN on IP_ADAPTER_ADDRESSES_LH
|
||||
*
|
||||
* For example, interface "Ethernet", with 2 unicast addresses:
|
||||
*
|
||||
* - 192.168.1.84
|
||||
* - 192.168.5.99
|
||||
*
|
||||
* The Prefix list has 8 elements:
|
||||
*
|
||||
* #1: 192.168.1.0/24 <- Network, use the PrefixLength for netmask
|
||||
* #2: 192.168.1.84/32 <- Host IP
|
||||
* #3: 192.168.1.255/32 <- Subnet broadcast
|
||||
*
|
||||
* #4: 192.168.5.0/24 <- Network
|
||||
* #5: 192.168.5.99/32 <- Host IP
|
||||
* #6: 192.168.5.255/32 <- Subnet broadcast
|
||||
*
|
||||
* #7: 224.0.0.0/4 <- Multicast
|
||||
* #8: 255.255.255.255/32 <- Broadcast
|
||||
*/
|
||||
|
||||
if (ptrAP && *ptrAP) {
|
||||
*ptrAP = (*ptrAP)->Next; /* skip net ip */
|
||||
if (*ptrAP) {
|
||||
*ptrAP = (*ptrAP)->Next; /* skip host ip */
|
||||
if (*ptrAP) {
|
||||
node->broadcast = *((*ptrAP)->Address.lpSockaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ptrUA = (*ptrUA)->Next;
|
||||
|
||||
/* Append this node to the last node (if any) */
|
||||
if (parentInfoNode) {
|
||||
parentInfoNode->next = node;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Returns -1 in case of failure */
|
||||
static textwindows int createHostInfo(
|
||||
struct NtIpAdapterAddresses *firstAdapter) {
|
||||
static bool once;
|
||||
struct NtIpAdapterAddresses *aa;
|
||||
struct NtIpAdapterUnicastAddress *ua;
|
||||
struct NtIpAdapterPrefix *ap;
|
||||
struct HostAdapterInfoNode *node = NULL;
|
||||
char baseName[IFNAMSIZ];
|
||||
char name[IFNAMSIZ];
|
||||
int count, i;
|
||||
/* __hostInfo must be empty */
|
||||
_unassert(__hostInfo == NULL);
|
||||
for (aa = firstAdapter; aa; aa = aa->Next) {
|
||||
/* Skip all the interfaces with no address and the ones that are not AF_INET
|
||||
*/
|
||||
if (!aa->FirstUnicastAddress ||
|
||||
aa->FirstUnicastAddress->Address.lpSockaddr->sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
/* Use max IFNAMSIZ-1 chars, leave the last char for eventual conflicts */
|
||||
tprecode16to8(baseName, IFNAMSIZ - 1, aa->FriendlyName);
|
||||
baseName[IFNAMSIZ - 2] = '\0';
|
||||
/* Replace any space with a '_' */
|
||||
for (i = 0; i < IFNAMSIZ - 2; ++i) {
|
||||
if (baseName[i] == ' ') baseName[i] = '_';
|
||||
if (!baseName[i]) break;
|
||||
}
|
||||
for (count = 0, ua = aa->FirstUnicastAddress, ap = aa->FirstPrefix;
|
||||
(ua != NULL) && (count < MAX_UNICAST_ADDR); ++count) {
|
||||
node = appendHostInfo(node, baseName, aa, &ua, &ap, count);
|
||||
if (!node) goto err;
|
||||
if (!__hostInfo) {
|
||||
__hostInfo = node;
|
||||
if (_cmpxchg(&once, false, true)) {
|
||||
atexit(freeHostInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Note: do we need to process the remaining adapter prefix?
|
||||
* ap - points to broadcast addr
|
||||
* ap->Next - points to interface multicast addr
|
||||
* Ignoring them for now
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
freeHostInfo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static textwindows int readAdapterAddresses(void) {
|
||||
uint32_t size, rc;
|
||||
struct NtIpAdapterAddresses *aa = NULL;
|
||||
/*
|
||||
* Calculate the required data size
|
||||
* Note: alternatively you can use AF_UNSPEC to also return IPv6 interfaces
|
||||
*/
|
||||
rc = GetAdaptersAddresses(AF_INET,
|
||||
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast |
|
||||
kNtGaaFlagSkipDnsServer |
|
||||
kNtGaaFlagIncludePrefix,
|
||||
NULL, /* Reserved */
|
||||
NULL, /* Ptr */
|
||||
&size);
|
||||
if (rc != kNtErrorBufferOverflow) {
|
||||
ebadf();
|
||||
goto err;
|
||||
}
|
||||
if (!_weaken(malloc) ||
|
||||
!(aa = (struct NtIpAdapterAddresses *)_weaken(malloc)(size))) {
|
||||
enomem();
|
||||
goto err;
|
||||
}
|
||||
/* Re-run GetAdaptersAddresses this time with a valid buffer */
|
||||
rc = GetAdaptersAddresses(AF_INET,
|
||||
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast |
|
||||
kNtGaaFlagSkipDnsServer |
|
||||
kNtGaaFlagIncludePrefix,
|
||||
// kNtGaaFlagIncludePrefix,
|
||||
NULL, aa, &size);
|
||||
if (rc != kNtErrorSuccess) {
|
||||
errno = GetLastError();
|
||||
goto err;
|
||||
}
|
||||
if (createHostInfo(aa) == -1) {
|
||||
goto err;
|
||||
}
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(aa);
|
||||
}
|
||||
return 0;
|
||||
err:
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(aa);
|
||||
}
|
||||
freeHostInfo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
||||
struct ifreq *ptr;
|
||||
struct NtIpAdapterAddresses *aa;
|
||||
struct HostAdapterInfoNode *node;
|
||||
if (__hostInfo) {
|
||||
freeHostInfo();
|
||||
}
|
||||
if (readAdapterAddresses() == -1) {
|
||||
return -1;
|
||||
}
|
||||
for (ptr = ifc->ifc_req, node = __hostInfo;
|
||||
(((char *)(ptr + 1) - ifc->ifc_buf) < ifc->ifc_len) && node;
|
||||
ptr++, node = node->next) {
|
||||
memcpy(ptr->ifr_name, node->name, IFNAMSIZ);
|
||||
memcpy(&ptr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
|
||||
}
|
||||
ifc->ifc_len = (char *)ptr - ifc->ifc_buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls settings on device.
|
||||
* Returns unicast addresses.
|
||||
*/
|
||||
static textwindows int ioctl_siocgifaddr_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Performs the SIOCGIFFLAGS operation */
|
||||
static textwindows int ioctl_siocgifflags_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
ifr->ifr_flags = node->flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Performs the SIOCGIFNETMASK operation */
|
||||
static textwindows int ioctl_siocgifnetmask_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_netmask, &node->netmask, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns broadcast address.
|
||||
*/
|
||||
static textwindows int ioctl_siocgifbrdaddr_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_broadaddr, &node->broadcast, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
||||
/*
|
||||
* We're 100% compatible with Linux.
|
||||
* BSD ABIs mainly differ by having sockaddr::sa_len
|
||||
* XNU uses a 32-bit length in a struct that's packed!
|
||||
*/
|
||||
int i, rc, fam;
|
||||
char *b, *p, *e;
|
||||
char ifcBsd[16];
|
||||
struct ifreq *req;
|
||||
uint32_t bufLen, ip;
|
||||
size_t numReq, bufMax;
|
||||
if (IsLinux()) {
|
||||
return sys_ioctl(fd, SIOCGIFCONF, ifc);
|
||||
}
|
||||
bufMax = 15000; /* conservative guesstimate */
|
||||
b = alloca(bufMax);
|
||||
memcpy(ifcBsd, &bufMax, 8); /* ifc_len */
|
||||
memcpy(ifcBsd + (IsXnu() ? 4 : 8), &b, 8); /* ifc_buf */
|
||||
if ((rc = sys_ioctl(fd, SIOCGIFCONF, &ifcBsd)) != -1) {
|
||||
/*
|
||||
* On XNU the size of the struct ifreq is different than Linux.
|
||||
* On Linux is fixed (40 bytes), but on XNU the struct sockaddr
|
||||
* has variable length, making the whole struct ifreq a variable
|
||||
* sized record.
|
||||
*/
|
||||
memcpy(&bufLen, b, 4);
|
||||
req = ifc->ifc_req;
|
||||
for (p = b, e = p + MIN(bufMax, READ32LE(ifcBsd)); p + 16 + 16 <= e;
|
||||
p += IsBsd() ? 16 + MAX(16, p[16] & 255) : 40) {
|
||||
fam = p[IsBsd() ? 17 : 16] & 255;
|
||||
if (fam != AF_INET) continue;
|
||||
ip = READ32BE(p + 20);
|
||||
bzero(req, sizeof(*req));
|
||||
memcpy(req->ifr_name, p, 16);
|
||||
memcpy(&req->ifr_addr, p + 16, 16);
|
||||
req->ifr_addr.sa_family = fam;
|
||||
((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip);
|
||||
++req;
|
||||
}
|
||||
ifc->ifc_len = (char *)req - ifc->ifc_buf; /* Adjust len */
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline void ioctl_sockaddr2linux(void *saddr) {
|
||||
char *p;
|
||||
if (saddr) {
|
||||
p = saddr;
|
||||
p[0] = p[1];
|
||||
p[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Used for all the ioctl that returns sockaddr structure that
|
||||
* requires adjustment between Linux and XNU
|
||||
*/
|
||||
static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) {
|
||||
if (sys_ioctl(fd, op, ifr) == -1) return -1;
|
||||
if (IsBsd()) ioctl_sockaddr2linux(&ifr->ifr_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ioctl_siocgifconf(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifconf_sysv(fd, arg);
|
||||
} else {
|
||||
return ioctl_siocgifconf_nt(fd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_siocgifaddr(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, arg);
|
||||
} else {
|
||||
return ioctl_siocgifaddr_nt(fd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_siocgifnetmask(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, arg);
|
||||
} else {
|
||||
return ioctl_siocgifnetmask_nt(fd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_siocgifbrdaddr(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, arg);
|
||||
} else {
|
||||
return ioctl_siocgifbrdaddr_nt(fd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_siocgifdstaddr(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, arg);
|
||||
} else {
|
||||
return enotsup();
|
||||
/* Not supported - Unknown how to find out how to retrieve the destination
|
||||
* address of a PPP from the interface list returned by the
|
||||
* GetAdaptersAddresses function
|
||||
*
|
||||
return ioctl_siocgifdstaddr_nt(fd, arg);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
static int ioctl_siocgifflags(int fd, void *arg) {
|
||||
if (!IsWindows()) {
|
||||
/* Both XNU and Linux are for once compatible here... */
|
||||
return ioctl_default(fd, SIOCGIFFLAGS, arg);
|
||||
} else {
|
||||
return ioctl_siocgifflags_nt(fd, arg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets "close on exec" on file descriptor the fast way.
|
||||
*
|
||||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
||||
*/
|
||||
static int ioctl_fioclex(int fd, int req) {
|
||||
int rc;
|
||||
if (fd >= 0) {
|
||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
||||
if (__isfdopen(fd)) {
|
||||
if (req == FIOCLEX) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
rc = sys_ioctl(fd, req);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs special i/o operation on file descriptor.
|
||||
*
|
||||
* @param request can be any of:
|
||||
*
|
||||
* - `FIONREAD` takes an `int *` and returns how many bytes of input
|
||||
* are available on a terminal or socket, waiting to be read. On
|
||||
* Windows this currently won't work for console file descriptors.
|
||||
*
|
||||
* - `TIOCGWINSZ` populates `struct winsize *` with the dimensions
|
||||
* of your teletypewriter. It's an alias for tcgetwinsize().
|
||||
*
|
||||
* - `TIOCSWINSZ` with the dimensions of your teletypewriter to
|
||||
* `struct winsize *`. It's an alias for tcsetwinsize().
|
||||
*
|
||||
* - `TIOCOUTQ` takes an `int *` and returns the number of bytes in
|
||||
* the terminal's output buffer. Only available on UNIX.
|
||||
*
|
||||
* - `TIOCSTI` takes a `const char *` and may be used to fake input
|
||||
* to a tty. This API isn't available on OpenBSD. Only available
|
||||
* on UNIX.
|
||||
*
|
||||
* - `TIOCNOTTY` takes an `int tty_fd` arg and makes it the
|
||||
* controlling terminal of the calling process, which should have
|
||||
* called setsid() beforehand.
|
||||
*
|
||||
* - `TIOCNOTTY` to give up the controlling terminal. Only available
|
||||
* on UNIX.
|
||||
*
|
||||
* - `TIOCNXCL` to give up exclusive mode on terminal. Only
|
||||
* available on UNIX.
|
||||
*
|
||||
* - `FIOCLEX` sets the `O_CLOEXEC` state (no arg) noting that this
|
||||
* polyfill may be removed in the future, and code should migrate
|
||||
* to the equivalent fcntl() api.
|
||||
*
|
||||
* - `FIONBIO` sets the `O_NONBLOCK` state (arg is `int *enabled`)
|
||||
* which is supported on Windows for sockets.
|
||||
*
|
||||
* - `FIONCLEX` clears the `O_CLOEXEC` state (no arg) noting that
|
||||
* this polyfill may be removed in the future, and code should
|
||||
* migrate to the equivalent fcntl() api.
|
||||
*
|
||||
* - `SIOCGIFCONF` takes an struct ifconf object of a given size,
|
||||
* whose arg is `struct ifconf *`. It implements the Linux style
|
||||
* and modifies the following:
|
||||
* - ifc_len: set it to the number of valid ifreq structures
|
||||
* representingthe interfaces
|
||||
* - ifc_ifcu.ifcu_req: sets the name of the interface for each
|
||||
* interface
|
||||
* The ifc_len is an input/output parameter: set it to the total
|
||||
* size of the ifcu_buf (ifcu_req) buffer on input.
|
||||
*
|
||||
* - `SIOCGIFNETMASK` populates a `struct ifconf *` record with the
|
||||
* network interface mask. This data structure should be obtained
|
||||
* by calling `SIOCGIFCONF`.
|
||||
*
|
||||
* - `SIOCGIFBRDADDR` populates a `struct ifconf *` record with the
|
||||
* network broadcast addr. This data structure should be obtained
|
||||
* by calling `SIOCGIFCONF`.
|
||||
*
|
||||
* - `TCGETS` isn't polyfilled; use tcgetattr()
|
||||
* - `TCSETS` isn't polyfilled; use tcsetattr()
|
||||
* - `TCSETSW` isn't polyfilled; use tcsetattr()
|
||||
* - `TCSETSF` isn't polyfilled; use tcsetattr()
|
||||
* - `TCXONC` isn't polyfilled; use tcflow()
|
||||
* - `TCSBRK` isn't polyfilled; use tcdrain()
|
||||
* - `TCFLSH` isn't polyfilled; use tcflush()
|
||||
* - `TIOCGPTN` isn't polyfilled; use ptsname()
|
||||
* - `TIOCGSID` isn't polyfilled; use tcgetsid()
|
||||
* - `TCSBRK` isn't polyfilled; use tcsendbreak()
|
||||
* - `TCSBRK` isn't polyfilled; use tcsendbreak()
|
||||
* - `TIOCSPGRP` isn't polyfilled; use tcsetpgrp()
|
||||
* - `TIOCSPTLCK` isn't polyfilled; use unlockpt()
|
||||
*
|
||||
* @restartable
|
||||
* @vforksafe
|
||||
*/
|
||||
int(ioctl)(int fd, uint64_t request, ...) {
|
||||
int ioctl(int fd, unsigned long request, ...) {
|
||||
int rc;
|
||||
void *arg;
|
||||
va_list va;
|
||||
va_start(va, request);
|
||||
arg = va_arg(va, void *);
|
||||
va_end(va);
|
||||
if (request == TIOCGWINSZ) return tcgetwinsize(fd, arg);
|
||||
if (request == TIOCSWINSZ) return tcsetwinsize(fd, arg);
|
||||
return __IOCTL_DISPATCH(EQUAL, -1, fd, request, arg);
|
||||
if (request == FIONBIO) {
|
||||
rc = ioctl_default(fd, request, arg);
|
||||
} else if (request == FIOCLEX) {
|
||||
rc = ioctl_fioclex(fd, request);
|
||||
} else if (request == FIONCLEX) {
|
||||
rc = ioctl_fioclex(fd, request);
|
||||
} else if (request == TIOCGWINSZ) {
|
||||
rc = tcgetwinsize(fd, arg);
|
||||
} else if (request == TIOCSWINSZ) {
|
||||
rc = tcsetwinsize(fd, arg);
|
||||
} else if (request == SIOCGIFCONF) {
|
||||
rc = ioctl_siocgifconf(fd, arg);
|
||||
} else if (request == SIOCGIFADDR) {
|
||||
rc = ioctl_siocgifaddr(fd, arg);
|
||||
} else if (request == SIOCGIFNETMASK) {
|
||||
rc = ioctl_siocgifnetmask(fd, arg);
|
||||
} else if (request == SIOCGIFBRDADDR) {
|
||||
rc = ioctl_siocgifbrdaddr(fd, arg);
|
||||
} else if (request == SIOCGIFDSTADDR) {
|
||||
rc = ioctl_siocgifdstaddr(fd, arg);
|
||||
} else if (request == SIOCGIFFLAGS) {
|
||||
rc = ioctl_siocgifflags(fd, arg);
|
||||
} else {
|
||||
rc = ioctl_default(fd, request, arg);
|
||||
}
|
||||
STRACE("ioctl(%d, %#lx, %p) → %d% m", fd, request, arg, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -1,66 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_IOCTL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_IOCTL_H_
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » ioctl ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
int ioctl(int, uint64_t, ...);
|
||||
|
||||
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) && defined(COSMO)
|
||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
||||
│ cosmopolitan § system calls » ioctl » undiamonding ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
||||
#define ioctl(FD, REQUEST, ...) \
|
||||
__IOCTL_DISPATCH(__EQUIVALENT, ioctl_default(FD, REQUEST, ##__VA_ARGS__), \
|
||||
FD, REQUEST, ##__VA_ARGS__)
|
||||
|
||||
#define __EQUIVALENT(X, Y) (__builtin_constant_p((X) == (Y)) && ((X) == (Y)))
|
||||
|
||||
#define __IOCTL_DISPATCH(CMP, DEFAULT, FD, REQUEST, ...) \
|
||||
({ \
|
||||
int ReZ; \
|
||||
if (CMP(REQUEST, SIOCGIFCONF)) { \
|
||||
ReZ = ioctl_siocgifconf(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFADDR)) { \
|
||||
ReZ = ioctl_siocgifaddr(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFNETMASK)) { \
|
||||
ReZ = ioctl_siocgifnetmask(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFBRDADDR)) { \
|
||||
ReZ = ioctl_siocgifbrdaddr(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFDSTADDR)) { \
|
||||
ReZ = ioctl_siocgifdstaddr(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, SIOCGIFFLAGS)) { \
|
||||
ReZ = ioctl_siocgifflags(FD, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, FIONBIO)) { \
|
||||
ReZ = ioctl_default(FD, REQUEST, ##__VA_ARGS__); \
|
||||
} else if (CMP(REQUEST, FIOCLEX)) { \
|
||||
ReZ = ioctl_fioclex(FD, REQUEST); \
|
||||
} else if (CMP(REQUEST, FIONCLEX)) { \
|
||||
ReZ = ioctl_fioclex(FD, REQUEST); \
|
||||
} else { \
|
||||
ReZ = DEFAULT; \
|
||||
} \
|
||||
ReZ; \
|
||||
})
|
||||
|
||||
int ioctl_default(int, uint64_t, ...);
|
||||
int ioctl_fioclex(int, int);
|
||||
int ioctl_siocgifaddr(int, ...);
|
||||
int ioctl_siocgifbrdaddr(int, ...);
|
||||
int ioctl_siocgifconf(int, ...);
|
||||
int ioctl_siocgifdstaddr(int, ...);
|
||||
int ioctl_siocgifflags(int, ...);
|
||||
int ioctl_siocgifnetmask(int, ...);
|
||||
|
||||
#endif /* GNUC && !ANSI */
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_IOCTL_H_ */
|
|
@ -1,52 +0,0 @@
|
|||
/*-*- 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/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
int ioctl_default(int fd, uint64_t request, ...) {
|
||||
int rc;
|
||||
void *arg;
|
||||
va_list va;
|
||||
int64_t handle;
|
||||
va_start(va, request);
|
||||
arg = va_arg(va, void *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return sys_ioctl(fd, request, arg);
|
||||
} else if (__isfdopen(fd)) {
|
||||
if (g_fds.p[fd].kind == kFdSocket) {
|
||||
handle = __getfdhandleactual(fd);
|
||||
if ((rc = _weaken(__sys_ioctlsocket_nt)(handle, request, arg)) != -1) {
|
||||
return rc;
|
||||
} else {
|
||||
return _weaken(__winsockerr)();
|
||||
}
|
||||
} else {
|
||||
return eopnotsupp();
|
||||
}
|
||||
} else {
|
||||
return ebadf();
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
/*-*- 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 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/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Sets "close on exec" on file descriptor the fast way.
|
||||
*
|
||||
* @see ioctl(fd, FIOCLEX, 0) dispatches here
|
||||
*/
|
||||
int ioctl_fioclex(int fd, int req) {
|
||||
int rc;
|
||||
if (fd >= 0) {
|
||||
if (IsWindows() || (fd < g_fds.n && g_fds.p[fd].kind == kFdZip)) {
|
||||
if (__isfdopen(fd)) {
|
||||
if (req == FIOCLEX) {
|
||||
g_fds.p[fd].flags |= O_CLOEXEC;
|
||||
} else {
|
||||
g_fds.p[fd].flags &= ~O_CLOEXEC;
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = ebadf();
|
||||
}
|
||||
} else {
|
||||
rc = sys_ioctl(fd, req);
|
||||
}
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("%s(%d, %d) → %d% m", "ioctl_fioclex", fd, req, rc);
|
||||
return rc;
|
||||
}
|
|
@ -1,414 +0,0 @@
|
|||
/*-*- 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/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/cmpxchg.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/iphlpapi.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/nt/struct/ipadapteraddresses.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/iff.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/* Maximum number of unicast addresses handled for each interface */
|
||||
#define MAX_UNICAST_ADDR 32
|
||||
#define MAX_NAME_CLASH ((int)('z' - 'a')) /* Allow a..z */
|
||||
|
||||
struct HostAdapterInfoNode {
|
||||
struct HostAdapterInfoNode *next;
|
||||
char name[IFNAMSIZ]; /* Obtained from FriendlyName */
|
||||
struct sockaddr unicast;
|
||||
struct sockaddr netmask;
|
||||
struct sockaddr broadcast;
|
||||
short flags;
|
||||
} * __hostInfo;
|
||||
|
||||
/* Frees all the nodes of the _hostInfo */
|
||||
static void freeHostInfo(void) {
|
||||
struct HostAdapterInfoNode *next, *node = __hostInfo;
|
||||
if (_weaken(free)) {
|
||||
while (node) {
|
||||
next = node->next;
|
||||
_weaken(free)(node);
|
||||
node = next;
|
||||
}
|
||||
}
|
||||
__hostInfo = NULL;
|
||||
}
|
||||
|
||||
/* Given a short adapter name, look into __hostInfo to see if there is
|
||||
* an adapter with the same name. Returns the pointer to the HostAdapterInfoNode
|
||||
* if found, or NULL if not found
|
||||
*/
|
||||
static struct HostAdapterInfoNode *findAdapterByName(const char *name) {
|
||||
struct HostAdapterInfoNode *node = __hostInfo;
|
||||
while (node) {
|
||||
if (!strncmp(name, node->name, IFNAMSIZ)) {
|
||||
return node;
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Creates a new HostAdapterInfoNode object, initializes it from
|
||||
* the given adapter, unicast address and address prefixes
|
||||
* and insert it in the __hostInfo.
|
||||
* Increments the pointers to the unicast addresses and
|
||||
* the address prefixes
|
||||
* Returns NULL if an error occurred or the newly created
|
||||
* HostAdapterInfoNode object (last in the list)
|
||||
*/
|
||||
struct HostAdapterInfoNode *appendHostInfo(
|
||||
struct HostAdapterInfoNode *parentInfoNode,
|
||||
const char *baseName, /* Max length = IFNAMSIZ-1 */
|
||||
const struct NtIpAdapterAddresses
|
||||
*aa, /* Top level adapter object being processed */
|
||||
struct NtIpAdapterUnicastAddress *
|
||||
*ptrUA, /* Ptr to ptr to unicast address list node */
|
||||
struct NtIpAdapterPrefix *
|
||||
*ptrAP, /* Ptr to ptr to Adapter prefix list node */
|
||||
int count) { /* count is used to create a unique name in case of alias */
|
||||
|
||||
struct HostAdapterInfoNode *temp;
|
||||
struct HostAdapterInfoNode *node;
|
||||
uint32_t ip, netmask, broadcast;
|
||||
struct sockaddr_in *a;
|
||||
int attemptNum;
|
||||
|
||||
if (!_weaken(calloc) || !(node = _weaken(calloc)(1, sizeof(*node)))) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(node->name, baseName, IFNAMSIZ);
|
||||
|
||||
/* Are there more than a single unicast address ? */
|
||||
if (count > 0 || ((*ptrUA)->Next != NULL)) {
|
||||
/* Yes, compose it using <baseName>:<count> */
|
||||
size_t nameLen = strlen(node->name);
|
||||
if (nameLen + 2 > IFNAMSIZ - 2) {
|
||||
/* Appending the ":x" will exceed the size, need to chop the end */
|
||||
nameLen -= 2;
|
||||
}
|
||||
node->name[nameLen - 2] = ':';
|
||||
node->name[nameLen - 1] = '0' + count;
|
||||
node->name[nameLen] = '\0';
|
||||
}
|
||||
|
||||
/* Is there a name clash with other interfaces? */
|
||||
for (attemptNum = 0; attemptNum < MAX_NAME_CLASH; ++attemptNum) {
|
||||
temp = findAdapterByName(node->name);
|
||||
if (!temp) {
|
||||
break;
|
||||
} else {
|
||||
/* Yes, this name has been already used, append an extra
|
||||
* character to resolve conflict. Note since the max length
|
||||
* of the string now is IFNAMSIZ-2, we have just enough space for this.
|
||||
* E.g. 'Ethernet_1' -> 'Ethernet_1a'
|
||||
*/
|
||||
size_t pos = strlen(node->name);
|
||||
node->name[pos] = 'a' + attemptNum;
|
||||
node->name[pos + 1] = '\0';
|
||||
/* Try again */
|
||||
}
|
||||
}
|
||||
|
||||
if (attemptNum == MAX_NAME_CLASH) {
|
||||
/* Cannot resolve the conflict */
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(node);
|
||||
}
|
||||
errno = EEXIST;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finally we got a unique short and friendly name */
|
||||
node->unicast = *((*ptrUA)->Address.lpSockaddr);
|
||||
if (*ptrUA == aa->FirstUnicastAddress) {
|
||||
short flags;
|
||||
/* This is the first unicast address of this interface
|
||||
* calculate the flags for this adapter. Flags to consider:
|
||||
* IFF_UP
|
||||
* IFF_BROADCAST ** TODO: We need to validate
|
||||
* IFF_LOOPBACK
|
||||
* IFF_POINTOPOINT
|
||||
* IFF_MULTICAST
|
||||
* IFF_RUNNING ** Same as IFF_UP for now
|
||||
* IFF_PROMISC ** NOT SUPPORTED, unknown how to retrieve it
|
||||
*/
|
||||
flags = 0;
|
||||
if (aa->OperStatus == kNtIfOperStatusUp) flags |= IFF_UP | IFF_RUNNING;
|
||||
if (aa->IfType == kNtIfTypePpp) flags |= IFF_POINTOPOINT;
|
||||
if (!(aa->Flags & kNtIpAdapterNoMulticast)) flags |= IFF_MULTICAST;
|
||||
if (aa->IfType == kNtIfTypeSoftwareLoopback) flags |= IFF_LOOPBACK;
|
||||
if (aa->FirstPrefix) flags |= IFF_BROADCAST;
|
||||
node->flags = flags;
|
||||
} else {
|
||||
/* Copy from previous node */
|
||||
node->flags = parentInfoNode->flags;
|
||||
}
|
||||
|
||||
ip = ntohl(
|
||||
((struct sockaddr_in *)(*ptrUA)->Address.lpSockaddr)->sin_addr.s_addr);
|
||||
netmask = (uint32_t)-1 << (32 - (*ptrUA)->OnLinkPrefixLength);
|
||||
broadcast = (ip & netmask) | (~netmask & -1);
|
||||
|
||||
a = (struct sockaddr_in *)&node->netmask;
|
||||
a->sin_family = AF_INET;
|
||||
a->sin_addr.s_addr = htonl(netmask);
|
||||
|
||||
a = (struct sockaddr_in *)&node->broadcast;
|
||||
a->sin_family = AF_INET;
|
||||
a->sin_addr.s_addr = htonl(broadcast);
|
||||
|
||||
/* Process the prefix and extract the netmask and broadcast */
|
||||
/* According to the doc:
|
||||
*
|
||||
* On Windows Vista and later, the linked IP_ADAPTER_PREFIX
|
||||
* structures pointed to by the FirstPrefix member include three
|
||||
* IP adapter prefixes for each IP address assigned to the
|
||||
* adapter. These include the host IP address prefix, the subnet
|
||||
* IP address prefix, and the subnet broadcast IP address prefix.
|
||||
* In addition, for each adapter there is a multicast address
|
||||
* prefix and a broadcast address prefix.
|
||||
* -Source: MSDN on IP_ADAPTER_ADDRESSES_LH
|
||||
*
|
||||
* For example, interface "Ethernet", with 2 unicast addresses:
|
||||
*
|
||||
* - 192.168.1.84
|
||||
* - 192.168.5.99
|
||||
*
|
||||
* The Prefix list has 8 elements:
|
||||
*
|
||||
* #1: 192.168.1.0/24 <- Network, use the PrefixLength for netmask
|
||||
* #2: 192.168.1.84/32 <- Host IP
|
||||
* #3: 192.168.1.255/32 <- Subnet broadcast
|
||||
*
|
||||
* #4: 192.168.5.0/24 <- Network
|
||||
* #5: 192.168.5.99/32 <- Host IP
|
||||
* #6: 192.168.5.255/32 <- Subnet broadcast
|
||||
*
|
||||
* #7: 224.0.0.0/4 <- Multicast
|
||||
* #8: 255.255.255.255/32 <- Broadcast
|
||||
*/
|
||||
|
||||
if (ptrAP && *ptrAP) {
|
||||
*ptrAP = (*ptrAP)->Next; /* skip net ip */
|
||||
if (*ptrAP) {
|
||||
*ptrAP = (*ptrAP)->Next; /* skip host ip */
|
||||
if (*ptrAP) {
|
||||
node->broadcast = *((*ptrAP)->Address.lpSockaddr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*ptrUA = (*ptrUA)->Next;
|
||||
|
||||
/* Append this node to the last node (if any) */
|
||||
if (parentInfoNode) {
|
||||
parentInfoNode->next = node;
|
||||
}
|
||||
|
||||
/* Success */
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Returns -1 in case of failure */
|
||||
static int createHostInfo(struct NtIpAdapterAddresses *firstAdapter) {
|
||||
static bool once;
|
||||
struct NtIpAdapterAddresses *aa;
|
||||
struct NtIpAdapterUnicastAddress *ua;
|
||||
struct NtIpAdapterPrefix *ap;
|
||||
struct HostAdapterInfoNode *node = NULL;
|
||||
char baseName[IFNAMSIZ];
|
||||
char name[IFNAMSIZ];
|
||||
int count, i;
|
||||
|
||||
/* __hostInfo must be empty */
|
||||
_unassert(__hostInfo == NULL);
|
||||
|
||||
for (aa = firstAdapter; aa; aa = aa->Next) {
|
||||
/* Skip all the interfaces with no address and the ones that are not AF_INET
|
||||
*/
|
||||
if (!aa->FirstUnicastAddress ||
|
||||
aa->FirstUnicastAddress->Address.lpSockaddr->sa_family != AF_INET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Use max IFNAMSIZ-1 chars, leave the last char for eventual conflicts */
|
||||
tprecode16to8(baseName, IFNAMSIZ - 1, aa->FriendlyName);
|
||||
baseName[IFNAMSIZ - 2] = '\0';
|
||||
/* Replace any space with a '_' */
|
||||
for (i = 0; i < IFNAMSIZ - 2; ++i) {
|
||||
if (baseName[i] == ' ') baseName[i] = '_';
|
||||
if (!baseName[i]) break;
|
||||
}
|
||||
for (count = 0, ua = aa->FirstUnicastAddress, ap = aa->FirstPrefix;
|
||||
(ua != NULL) && (count < MAX_UNICAST_ADDR); ++count) {
|
||||
node = appendHostInfo(node, baseName, aa, &ua, &ap, count);
|
||||
if (!node) goto err;
|
||||
if (!__hostInfo) {
|
||||
__hostInfo = node;
|
||||
if (_cmpxchg(&once, false, true)) {
|
||||
atexit(freeHostInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Note: do we need to process the remaining adapter prefix?
|
||||
* ap - points to broadcast addr
|
||||
* ap->Next - points to interface multicast addr
|
||||
* Ignoring them for now
|
||||
*/
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
freeHostInfo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int readAdapterAddresses(void) {
|
||||
uint32_t size, rc;
|
||||
struct NtIpAdapterAddresses *aa = NULL;
|
||||
|
||||
/* Calculate the required data size
|
||||
* Note: alternatively you can use AF_UNSPEC to also return IPv6 interfaces
|
||||
*/
|
||||
rc = GetAdaptersAddresses(AF_INET,
|
||||
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast |
|
||||
kNtGaaFlagSkipDnsServer |
|
||||
kNtGaaFlagIncludePrefix,
|
||||
NULL, /* Reserved */
|
||||
NULL, /* Ptr */
|
||||
&size);
|
||||
if (rc != kNtErrorBufferOverflow) {
|
||||
ebadf();
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!_weaken(malloc) ||
|
||||
!(aa = (struct NtIpAdapterAddresses *)_weaken(malloc)(size))) {
|
||||
enomem();
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Re-run GetAdaptersAddresses this time with a valid buffer */
|
||||
rc = GetAdaptersAddresses(AF_INET,
|
||||
kNtGaaFlagSkipAnycast | kNtGaaFlagSkipMulticast |
|
||||
kNtGaaFlagSkipDnsServer |
|
||||
kNtGaaFlagIncludePrefix,
|
||||
// kNtGaaFlagIncludePrefix,
|
||||
NULL, aa, &size);
|
||||
if (rc != kNtErrorSuccess) {
|
||||
errno = GetLastError();
|
||||
goto err;
|
||||
}
|
||||
if (createHostInfo(aa) == -1) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(aa);
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (_weaken(free)) {
|
||||
_weaken(free)(aa);
|
||||
}
|
||||
freeHostInfo();
|
||||
return -1;
|
||||
}
|
||||
|
||||
textwindows int ioctl_siocgifconf_nt(int fd, struct ifconf *ifc) {
|
||||
struct NtIpAdapterAddresses *aa;
|
||||
struct HostAdapterInfoNode *node;
|
||||
struct ifreq *ptr;
|
||||
|
||||
if (__hostInfo) {
|
||||
freeHostInfo();
|
||||
}
|
||||
|
||||
if (readAdapterAddresses() == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (ptr = ifc->ifc_req, node = __hostInfo;
|
||||
(((char *)(ptr + 1) - ifc->ifc_buf) < ifc->ifc_len) && node;
|
||||
ptr++, node = node->next) {
|
||||
memcpy(ptr->ifr_name, node->name, IFNAMSIZ);
|
||||
memcpy(&ptr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
|
||||
}
|
||||
ifc->ifc_len = (char *)ptr - ifc->ifc_buf;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns unicast addresses.
|
||||
*/
|
||||
int ioctl_siocgifaddr_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_addr, &node->unicast, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Performs the SIOCGIFFLAGS operation */
|
||||
int ioctl_siocgifflags_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
ifr->ifr_flags = node->flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Performs the SIOCGIFNETMASK operation */
|
||||
int ioctl_siocgifnetmask_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_netmask, &node->netmask, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns broadcast address.
|
||||
*/
|
||||
int ioctl_siocgifbrdaddr_nt(int fd, struct ifreq *ifr) {
|
||||
struct HostAdapterInfoNode *node;
|
||||
node = findAdapterByName(ifr->ifr_name);
|
||||
if (!node) return ebadf();
|
||||
memcpy(&ifr->ifr_broadaddr, &node->broadcast, sizeof(struct sockaddr));
|
||||
return 0;
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
/*-*- 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/assert.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/sio.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/* SIOCGIFCONF:
|
||||
* Takes an struct ifconf object of a given size
|
||||
* Modifies the following:
|
||||
* - ifc_len: set it to the number of valid ifreq structures representing
|
||||
* the interfaces
|
||||
* - ifc_ifcu.ifcu_req: sets the name of the interface for each interface
|
||||
* The ifc_len is an input/output parameter: set it to the total size of
|
||||
* the ifcu_buf (ifcu_req) buffer on input.
|
||||
*/
|
||||
int ioctl_siocgifconf_nt(int, struct ifconf *) _Hide;
|
||||
int ioctl_siocgifaddr_nt(int, struct ifreq *) _Hide;
|
||||
int ioctl_siocgifflags_nt(int, struct ifreq *) _Hide;
|
||||
int ioctl_siocgifnetmask_nt(int, struct ifreq *) _Hide;
|
||||
int ioctl_siocgifbrdaddr_nt(int, struct ifreq *) _Hide;
|
||||
|
||||
static int ioctl_siocgifconf_sysv(int fd, struct ifconf *ifc) {
|
||||
/*
|
||||
* We're 100% compatible with Linux.
|
||||
* BSD ABIs mainly differ by having sockaddr::sa_len
|
||||
* XNU uses a 32-bit length in a struct that's packed!
|
||||
*/
|
||||
int i, rc, fam;
|
||||
char *b, *p, *e;
|
||||
char ifcBsd[16];
|
||||
struct ifreq *req;
|
||||
uint32_t bufLen, ip;
|
||||
size_t numReq, bufMax;
|
||||
if (IsLinux()) return sys_ioctl(fd, SIOCGIFCONF, ifc);
|
||||
if (!_weaken(malloc)) return enomem();
|
||||
bufMax = 15000; /* conservative guesstimate */
|
||||
if (!(b = _weaken(malloc)(bufMax))) return enomem();
|
||||
memcpy(ifcBsd, &bufMax, 8); /* ifc_len */
|
||||
memcpy(ifcBsd + (IsXnu() ? 4 : 8), &b, 8); /* ifc_buf */
|
||||
if ((rc = sys_ioctl(fd, SIOCGIFCONF, &ifcBsd)) != -1) {
|
||||
/*
|
||||
* On XNU the size of the struct ifreq is different than Linux.
|
||||
* On Linux is fixed (40 bytes), but on XNU the struct sockaddr
|
||||
* has variable length, making the whole struct ifreq a variable
|
||||
* sized record.
|
||||
*/
|
||||
memcpy(&bufLen, b, 4);
|
||||
req = ifc->ifc_req;
|
||||
for (p = b, e = p + MIN(bufMax, READ32LE(ifcBsd)); p + 16 + 16 <= e;
|
||||
p += IsBsd() ? 16 + MAX(16, p[16] & 255) : 40) {
|
||||
fam = p[IsBsd() ? 17 : 16] & 255;
|
||||
if (fam != AF_INET) continue;
|
||||
ip = READ32BE(p + 20);
|
||||
bzero(req, sizeof(*req));
|
||||
memcpy(req->ifr_name, p, 16);
|
||||
memcpy(&req->ifr_addr, p + 16, 16);
|
||||
req->ifr_addr.sa_family = fam;
|
||||
((struct sockaddr_in *)&req->ifr_addr)->sin_addr.s_addr = htonl(ip);
|
||||
++req;
|
||||
}
|
||||
ifc->ifc_len = (char *)req - ifc->ifc_buf; /* Adjust len */
|
||||
}
|
||||
if (_weaken(free)) _weaken(free)(b);
|
||||
return rc;
|
||||
}
|
||||
|
||||
forceinline void Sockaddr2linux(void *saddr) {
|
||||
char *p;
|
||||
if (saddr) {
|
||||
p = saddr;
|
||||
p[0] = p[1];
|
||||
p[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for all the ioctl that returns sockaddr structure that
|
||||
* requires adjustment between Linux and XNU
|
||||
*/
|
||||
static int ioctl_siocgifaddr_sysv(int fd, uint64_t op, struct ifreq *ifr) {
|
||||
if (sys_ioctl(fd, op, ifr) == -1) return -1;
|
||||
if (IsBsd()) Sockaddr2linux(&ifr->ifr_addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns information about network interfaces.
|
||||
*
|
||||
* @see ioctl(fd, SIOCGIFCONF, tio) dispatches here
|
||||
*/
|
||||
int ioctl_siocgifconf(int fd, ...) {
|
||||
int rc;
|
||||
va_list va;
|
||||
struct ifconf *ifc;
|
||||
va_start(va, fd);
|
||||
ifc = va_arg(va, struct ifconf *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
rc = ioctl_siocgifconf_sysv(fd, ifc);
|
||||
} else {
|
||||
rc = ioctl_siocgifconf_nt(fd, ifc);
|
||||
}
|
||||
STRACE("%s(%d) → %d% m", "ioctl_siocgifconf", fd, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ioctl_siocgifaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFADDR, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifaddr_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifnetmask(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFNETMASK, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifnetmask_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifbrdaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFBRDADDR, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifbrdaddr_nt(fd, ifr);
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifdstaddr(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
return ioctl_siocgifaddr_sysv(fd, SIOCGIFDSTADDR, ifr);
|
||||
} else {
|
||||
return enotsup();
|
||||
/* Not supported - Unknown how to find out how to retrieve the destination
|
||||
* address of a PPP from the interface list returned by the
|
||||
* GetAdaptersAddresses function
|
||||
*
|
||||
return ioctl_siocgifdstaddr_nt(fd, ifc);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
int ioctl_siocgifflags(int fd, ...) {
|
||||
va_list va;
|
||||
struct ifreq *ifr;
|
||||
va_start(va, fd);
|
||||
ifr = va_arg(va, struct ifreq *);
|
||||
va_end(va);
|
||||
if (!IsWindows()) {
|
||||
/* Both XNU and Linux are for once compatible here... */
|
||||
return ioctl_default(fd, SIOCGIFFLAGS, ifr);
|
||||
} else {
|
||||
return ioctl_siocgifflags_nt(fd, ifr);
|
||||
}
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/blockcancel.internal.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/struct/winsize.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/metatermios.internal.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef LIBC_ISYSTEM_SYS_IOCTL_H_
|
||||
#define LIBC_ISYSTEM_SYS_IOCTL_H_
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/syscall-sysv.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/strace.internal.h"
|
||||
|
|
|
@ -351,6 +351,7 @@ syscon fcntl2 F_GETFD 1 1 1 1 1 1 1 1 # unix consensus & fak
|
|||
syscon fcntl2 F_SETFD 2 2 2 2 2 2 2 2 # unix consensus & faked nt
|
||||
syscon fcntl2 F_GETFL 3 3 3 3 3 3 3 3 # unix consensus & faked nt
|
||||
syscon fcntl2 F_SETFL 4 4 4 4 4 4 4 4 # unix consensus & faked nt
|
||||
syscon fcntl F_DUPFD_CLOEXEC 0x0406 0x0406 67 67 17 10 12 0x0406 # Linux 2.6.24+; faked nt
|
||||
syscon fcntl2 F_SETOWN 8 8 6 6 6 6 6 -1 # bsd consensus
|
||||
syscon fcntl2 F_GETOWN 9 9 5 5 5 5 5 -1 # bsd consensus
|
||||
syscon fcntl2 F_SETOWN_EX 15 15 -1 -1 -1 -1 -1 -1 # TODO(jart): polyfill
|
||||
|
@ -362,7 +363,6 @@ syscon fcntl3 F_SETNOSIGPIPE -1 -1 73 73 -1 -1 14 -1 #
|
|||
syscon fcntl3 F_GETNOSIGPIPE -1 -1 74 74 -1 -1 13 -1 #
|
||||
syscon fcntl3 F_GETPATH -1 -1 50 50 -1 -1 15 -1 # geth path associated with fd into buffer with PATH_MAX (1024) bytes
|
||||
syscon fcntl3 FD_CLOEXEC 1 1 1 1 1 1 1 1 # unix consensus & faked nt
|
||||
syscon fcntl F_DUPFD_CLOEXEC 0x0406 0x0406 67 67 17 10 12 0x0406 # Linux 2.6.24+; faked nt
|
||||
syscon fcntl F_MAXFD -1 -1 -1 -1 -1 -1 11 -1 #
|
||||
syscon fcntl F_NOTIFY 0x0402 0x0402 -1 -1 -1 -1 -1 -1
|
||||
syscon fcntl F_SETPIPE_SZ 0x0407 0x0407 -1 -1 -1 -1 -1 -1
|
||||
|
@ -399,14 +399,6 @@ syscon fcntl F_GETOWN_EX 0x10 0x10 -1 -1 -1 -1 -1 -1
|
|||
syscon fcntl F_SETLEASE 0x0400 0x0400 -1 106 -1 -1 -1 -1
|
||||
syscon fcntl F_GETLEASE 0x0401 0x0401 -1 107 -1 -1 -1 -1
|
||||
|
||||
syscon ioctl FIONBIO 0x5421 0x5421 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e # BSD-The New Technology consensus; FIONBIO is traditional O_NONBLOCK; see F_SETFL for re-imagined api
|
||||
syscon ioctl FIOASYNC 0x5452 0x5452 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d # BSD-The New Technology consensus
|
||||
syscon ioctl FIONREAD 0x541b 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f # BSD-The New Technology consensus; bytes waiting in FD's input buffer
|
||||
syscon ioctl FIOCLEX 0x5451 0x5451 0x20006601 0x20006601 0x20006601 0x20006601 0x20006601 0x5451 # sets "close on exec" on file descriptor the fast way; faked nt
|
||||
syscon ioctl FIONCLEX 0x5450 0x5450 0x20006602 0x20006602 0x20006602 0x20006602 0x20006602 0x5450 # clears "close on exec" on file descriptor the fast way; faked nt
|
||||
#syscon ioctl FIONWRITE 0x0 0x0 0x0 0x0 0x40046677 0x0 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
||||
#syscon ioctl FIONSPACE 0x0 0x0 0x0 0x0 0x40046676 0x0 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
||||
|
||||
# openat(), fstatat(), linkat(), etc. magnums
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
|
@ -944,68 +936,76 @@ syscon ptrace PTRACE_EVENT_STOP 128 128 -1 -1 -1 -1 -1 -1
|
|||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon clone CLONE_VM 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 0x00000100 # intentionally symbolic so we can tell if clone() is being used to create threads
|
||||
|
||||
# socket ioctl()
|
||||
# ioctl() requests
|
||||
#
|
||||
# group name GNU/Systemd GNU/Systemd (Aarch64) XNU's Not UNIX! MacOS (Arm64) FreeBSD OpenBSD NetBSD The New Technology Commentary
|
||||
syscon sio SIOCATMARK 0x8905 0x8905 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 # use sockatmark(); determines if oob is available; bsd consensus
|
||||
syscon sio SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
|
||||
syscon sio SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
|
||||
syscon sio SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
|
||||
syscon sio SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0 # bsd consensus
|
||||
syscon sio SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0 # bsd consensus
|
||||
syscon sio SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0 # bsd consensus
|
||||
syscon sio SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0 # bsd consensus
|
||||
syscon sio SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0 # bsd consensus
|
||||
syscon sio SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0 # bsd consensus
|
||||
syscon sio SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0 # bsd consensus
|
||||
syscon sio SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0 # bsd consensus
|
||||
syscon sio SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0 # bsd consensus
|
||||
syscon sio SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0 # bsd consensus
|
||||
syscon sio SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0 # bsd consensus
|
||||
syscon sio SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0 # bsd consensus
|
||||
syscon sio SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0 # bsd consensus
|
||||
syscon sio SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0 # bsd consensus
|
||||
syscon sio SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
|
||||
syscon sio SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0
|
||||
syscon sio SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0
|
||||
syscon sio SIOCGIFINDEX 0x8933 0x8933 0 0 0xc0206920 0 0 0
|
||||
syscon sio SIOCSIFNAME 0x8923 0x8923 0 0 0x80206928 0 0 0
|
||||
syscon sio SIOCADDDLCI 0x8980 0x8980 0 0 0 0 0 0
|
||||
syscon sio SIOCADDRT 0x890b 0x890b 0 0 0 0 0 0
|
||||
syscon sio SIOCDARP 0x8953 0x8953 0 0 0 0 0 0
|
||||
syscon sio SIOCDELDLCI 0x8981 0x8981 0 0 0 0 0 0
|
||||
syscon sio SIOCDELRT 0x890c 0x890c 0 0 0 0 0 0
|
||||
syscon sio SIOCDEVPRIVATE 0x89f0 0x89f0 0 0 0 0 0 0
|
||||
syscon sio SIOCDRARP 0x8960 0x8960 0 0 0 0 0 0
|
||||
syscon sio SIOCGARP 0x8954 0x8954 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFBR 0x8940 0x8940 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFCOUNT 0x8938 0x8938 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFENCAP 0x8925 0x8925 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFHWADDR 0x8927 0x8927 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFMAP 0x8970 0x8970 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFMEM 0x891f 0x891f 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFNAME 0x8910 0x8910 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFPFLAGS 0x8935 0x8935 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFSLAVE 0x8929 0x8929 0 0 0 0 0 0
|
||||
syscon sio SIOCGIFTXQLEN 0x8942 0x8942 0 0 0 0 0 0
|
||||
syscon sio SIOCGRARP 0x8961 0x8961 0 0 0 0 0 0
|
||||
syscon sio SIOCGSTAMP 0x8906 0x8906 0 0 0 0 0 0
|
||||
syscon sio SIOCGSTAMPNS 0x8907 0x8907 0 0 0 0 0 0
|
||||
syscon sio SIOCPROTOPRIVATE 0x89e0 0x89e0 0 0 0 0 0 0
|
||||
syscon sio SIOCRTMSG 0x890d 0x890d 0 0 0 0 0 0
|
||||
syscon sio SIOCSARP 0x8955 0x8955 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFBR 0x8941 0x8941 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFENCAP 0x8926 0x8926 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFHWADDR 0x8924 0x8924 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFHWBROADCAST 0x8937 0x8937 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFLINK 0x8911 0x8911 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFMAP 0x8971 0x8971 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFMEM 0x8920 0x8920 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFPFLAGS 0x8934 0x8934 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFSLAVE 0x8930 0x8930 0 0 0 0 0 0
|
||||
syscon sio SIOCSIFTXQLEN 0x8943 0x8943 0 0 0 0 0 0
|
||||
syscon sio SIOCSRARP 0x8962 0x8962 0 0 0 0 0 0
|
||||
syscon sio SIOGIFINDEX 0x8933 0x8933 0 0 0 0 0 0
|
||||
syscon ioctl FIONBIO 0x5421 0x5421 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e 0x8004667e # BSD-The New Technology consensus; FIONBIO is traditional O_NONBLOCK; see F_SETFL for re-imagined api
|
||||
syscon ioctl FIOASYNC 0x5452 0x5452 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d # BSD-The New Technology consensus
|
||||
syscon ioctl FIONREAD 0x541b 0x541b 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f 0x4004667f # BSD-The New Technology consensus; bytes waiting in FD's input buffer
|
||||
syscon ioctl FIOCLEX 0x5451 0x5451 0x20006601 0x20006601 0x20006601 0x20006601 0x20006601 0x5451 # sets "close on exec" on file descriptor the fast way; faked nt
|
||||
syscon ioctl FIONCLEX 0x5450 0x5450 0x20006602 0x20006602 0x20006602 0x20006602 0x20006602 0x5450 # clears "close on exec" on file descriptor the fast way; faked nt
|
||||
#syscon ioctl FIONWRITE 0x0 0x0 0x0 0x0 0x40046677 0x0 0x0 -1 # [FreeBSD Generalization] bytes queued in FD's output buffer (same as TIOCOUTQ for TTY FDs; see also SO_SNDBUF)
|
||||
#syscon ioctl FIONSPACE 0x0 0x0 0x0 0x0 0x40046676 0x0 0x0 -1 # [FreeBSD Generalization] capacity of FD's output buffer, e.g. equivalent to TIOCGSERIAL w/ UART
|
||||
syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
|
||||
syscon ioctl SIOCATMARK 0x8905 0x8905 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 # use sockatmark(); determines if oob is available; bsd consensus
|
||||
syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
|
||||
syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
|
||||
syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0 # bsd consensus
|
||||
syscon ioctl SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0 # bsd consensus
|
||||
syscon ioctl SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0 # bsd consensus
|
||||
syscon ioctl SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0 # bsd consensus
|
||||
syscon ioctl SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0
|
||||
syscon ioctl SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0
|
||||
|
||||
syscon ioctl SIOCGIFINDEX 0x8933 0x8933 0 0 0xc0206920 0 0 0
|
||||
syscon ioctl SIOCSIFNAME 0x8923 0x8923 0 0 0x80206928 0 0 0
|
||||
syscon ioctl SIOCADDDLCI 0x8980 0x8980 0 0 0 0 0 0
|
||||
syscon ioctl SIOCADDRT 0x890b 0x890b 0 0 0 0 0 0
|
||||
syscon ioctl SIOCDARP 0x8953 0x8953 0 0 0 0 0 0
|
||||
syscon ioctl SIOCDELDLCI 0x8981 0x8981 0 0 0 0 0 0
|
||||
syscon ioctl SIOCDELRT 0x890c 0x890c 0 0 0 0 0 0
|
||||
syscon ioctl SIOCDEVPRIVATE 0x89f0 0x89f0 0 0 0 0 0 0
|
||||
syscon ioctl SIOCDRARP 0x8960 0x8960 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGARP 0x8954 0x8954 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFBR 0x8940 0x8940 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFCOUNT 0x8938 0x8938 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFENCAP 0x8925 0x8925 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFHWADDR 0x8927 0x8927 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFMAP 0x8970 0x8970 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFMEM 0x891f 0x891f 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFNAME 0x8910 0x8910 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFPFLAGS 0x8935 0x8935 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFSLAVE 0x8929 0x8929 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGIFTXQLEN 0x8942 0x8942 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGRARP 0x8961 0x8961 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGSTAMP 0x8906 0x8906 0 0 0 0 0 0
|
||||
syscon ioctl SIOCGSTAMPNS 0x8907 0x8907 0 0 0 0 0 0
|
||||
syscon ioctl SIOCPROTOPRIVATE 0x89e0 0x89e0 0 0 0 0 0 0
|
||||
syscon ioctl SIOCRTMSG 0x890d 0x890d 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSARP 0x8955 0x8955 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFBR 0x8941 0x8941 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFENCAP 0x8926 0x8926 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFHWADDR 0x8924 0x8924 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFHWBROADCAST 0x8937 0x8937 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFLINK 0x8911 0x8911 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFMAP 0x8971 0x8971 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFMEM 0x8920 0x8920 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFPFLAGS 0x8934 0x8934 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFSLAVE 0x8930 0x8930 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSIFTXQLEN 0x8943 0x8943 0 0 0 0 0 0
|
||||
syscon ioctl SIOCSRARP 0x8962 0x8962 0 0 0 0 0 0
|
||||
syscon ioctl SIOGIFINDEX 0x8933 0x8933 0 0 0 0 0 0
|
||||
|
||||
# socket() address families
|
||||
#
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
/*
|
||||
* full set of fcntl() commands
|
||||
* many are only provided by a single platform
|
||||
* will be equal to -1 when not available on host
|
||||
*/
|
||||
extern const int F_BARRIERFSYNC;
|
||||
extern const int F_DUPFD;
|
||||
extern const int F_DUPFD_CLOEXEC;
|
||||
|
@ -42,34 +47,28 @@ extern const int F_WRLCK;
|
|||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
||||
#define F_DUPFD 0
|
||||
#define F_GETFD 1
|
||||
#define F_SETFD 2
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
|
||||
/*
|
||||
* portable fcntl() commands
|
||||
*/
|
||||
#define F_DUPFD 0
|
||||
#define F_GETFD 1
|
||||
#define F_SETFD 2
|
||||
#define F_GETFL 3
|
||||
#define F_SETFL 4
|
||||
#define F_DUPFD_CLOEXEC F_DUPFD_CLOEXEC
|
||||
#define F_GETLEASE F_GETLEASE
|
||||
#define F_GETLK F_GETLK
|
||||
#define F_GETLK64 F_GETLK64
|
||||
#define F_GETOWN F_GETOWN
|
||||
#define F_GETPATH F_GETPATH
|
||||
#define F_GETPIPE_SZ F_GETPIPE_SZ
|
||||
#define F_GETSIG F_GETSIG
|
||||
#define F_MAXFD F_MAXFD
|
||||
#define F_NOCACHE F_NOCACHE
|
||||
#define F_NOTIFY F_NOTIFY
|
||||
#define F_RDLCK F_RDLCK
|
||||
#define F_SETLEASE F_SETLEASE
|
||||
#define F_SETLK F_SETLK
|
||||
#define F_SETLK64 F_SETLK64
|
||||
#define F_SETLKW F_SETLKW
|
||||
#define F_SETLKW64 F_SETLKW64
|
||||
#define F_SETOWN F_SETOWN
|
||||
#define F_SETPIPE_SZ F_SETPIPE_SZ
|
||||
#define F_SETSIG F_SETSIG
|
||||
#define F_UNLCK F_UNLCK
|
||||
#define F_WRLCK F_WRLCK
|
||||
|
||||
/*
|
||||
* posix advisory locks
|
||||
* polyfilled poorly on windows
|
||||
*/
|
||||
#define F_SETLK F_SETLK
|
||||
#define F_SETLK64 F_SETLK64
|
||||
#define F_SETLKW F_SETLKW
|
||||
#define F_SETLKW64 F_SETLKW64
|
||||
#define F_GETLK F_GETLK
|
||||
#define F_GETLK64 F_GETLK64
|
||||
#define F_RDLCK F_RDLCK
|
||||
#define F_UNLCK F_UNLCK
|
||||
#define F_WRLCK F_WRLCK
|
||||
|
||||
#endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_F_H_ */
|
||||
|
|
|
@ -3,126 +3,88 @@
|
|||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const uint64_t SIOCADDDLCI;
|
||||
extern const uint64_t SIOCADDMULTI;
|
||||
extern const uint64_t SIOCADDRT;
|
||||
extern const uint64_t SIOCATMARK;
|
||||
extern const uint64_t SIOCDARP;
|
||||
extern const uint64_t SIOCDELDLCI;
|
||||
extern const uint64_t SIOCDELMULTI;
|
||||
extern const uint64_t SIOCDELRT;
|
||||
extern const uint64_t SIOCDEVPRIVATE;
|
||||
extern const uint64_t SIOCDIFADDR;
|
||||
extern const uint64_t SIOCDRARP;
|
||||
extern const uint64_t SIOCGARP;
|
||||
extern const uint64_t SIOCGIFADDR;
|
||||
extern const uint64_t SIOCGIFBR;
|
||||
extern const uint64_t SIOCGIFBRDADDR;
|
||||
extern const uint64_t SIOCGIFCONF;
|
||||
extern const uint64_t SIOCGIFCOUNT;
|
||||
extern const uint64_t SIOCGIFDSTADDR;
|
||||
extern const uint64_t SIOCGIFENCAP;
|
||||
extern const uint64_t SIOCGIFFLAGS;
|
||||
extern const uint64_t SIOCGIFHWADDR;
|
||||
extern const uint64_t SIOCGIFINDEX;
|
||||
extern const uint64_t SIOCGIFMAP;
|
||||
extern const uint64_t SIOCGIFMEM;
|
||||
extern const uint64_t SIOCGIFMETRIC;
|
||||
extern const uint64_t SIOCGIFMTU;
|
||||
extern const uint64_t SIOCGIFNAME;
|
||||
extern const uint64_t SIOCGIFNETMASK;
|
||||
extern const uint64_t SIOCGIFPFLAGS;
|
||||
extern const uint64_t SIOCGIFSLAVE;
|
||||
extern const uint64_t SIOCGIFTXQLEN;
|
||||
extern const uint64_t SIOCGPGRP;
|
||||
extern const uint64_t SIOCGRARP;
|
||||
extern const uint64_t SIOCGSTAMP;
|
||||
extern const uint64_t SIOCGSTAMPNS;
|
||||
extern const uint64_t SIOCPROTOPRIVATE;
|
||||
extern const uint64_t SIOCRTMSG;
|
||||
extern const uint64_t SIOCSARP;
|
||||
extern const uint64_t SIOCSIFADDR;
|
||||
extern const uint64_t SIOCSIFBR;
|
||||
extern const uint64_t SIOCSIFBRDADDR;
|
||||
extern const uint64_t SIOCSIFDSTADDR;
|
||||
extern const uint64_t SIOCSIFENCAP;
|
||||
extern const uint64_t SIOCSIFFLAGS;
|
||||
extern const uint64_t SIOCSIFHWADDR;
|
||||
extern const uint64_t SIOCSIFHWBROADCAST;
|
||||
extern const uint64_t SIOCSIFLINK;
|
||||
extern const uint64_t SIOCSIFMAP;
|
||||
extern const uint64_t SIOCSIFMEM;
|
||||
extern const uint64_t SIOCSIFMETRIC;
|
||||
extern const uint64_t SIOCSIFMTU;
|
||||
extern const uint64_t SIOCSIFNAME;
|
||||
extern const uint64_t SIOCSIFNETMASK;
|
||||
extern const uint64_t SIOCSIFPFLAGS;
|
||||
extern const uint64_t SIOCSIFSLAVE;
|
||||
extern const uint64_t SIOCSIFTXQLEN;
|
||||
extern const uint64_t SIOCSPGRP;
|
||||
extern const uint64_t SIOCSRARP;
|
||||
extern const uint64_t SIOGIFINDEX;
|
||||
extern const unsigned long SIOCADDDLCI;
|
||||
extern const unsigned long SIOCADDMULTI;
|
||||
extern const unsigned long SIOCADDRT;
|
||||
extern const unsigned long SIOCATMARK; /* use sockatmark() */
|
||||
extern const unsigned long SIOCDARP;
|
||||
extern const unsigned long SIOCDELDLCI;
|
||||
extern const unsigned long SIOCDELMULTI;
|
||||
extern const unsigned long SIOCDELRT;
|
||||
extern const unsigned long SIOCDEVPRIVATE;
|
||||
extern const unsigned long SIOCDIFADDR;
|
||||
extern const unsigned long SIOCDRARP;
|
||||
extern const unsigned long SIOCGARP;
|
||||
extern const unsigned long SIOCGIFADDR;
|
||||
extern const unsigned long SIOCGIFBR;
|
||||
extern const unsigned long SIOCGIFBRDADDR;
|
||||
extern const unsigned long SIOCGIFCONF;
|
||||
extern const unsigned long SIOCGIFCOUNT;
|
||||
extern const unsigned long SIOCGIFDSTADDR;
|
||||
extern const unsigned long SIOCGIFENCAP;
|
||||
extern const unsigned long SIOCGIFFLAGS;
|
||||
extern const unsigned long SIOCGIFHWADDR;
|
||||
extern const unsigned long SIOCGIFINDEX;
|
||||
extern const unsigned long SIOCGIFMAP;
|
||||
extern const unsigned long SIOCGIFMEM;
|
||||
extern const unsigned long SIOCGIFMETRIC;
|
||||
extern const unsigned long SIOCGIFMTU;
|
||||
extern const unsigned long SIOCGIFNAME;
|
||||
extern const unsigned long SIOCGIFNETMASK;
|
||||
extern const unsigned long SIOCGIFPFLAGS;
|
||||
extern const unsigned long SIOCGIFSLAVE;
|
||||
extern const unsigned long SIOCGIFTXQLEN;
|
||||
extern const unsigned long SIOCGPGRP;
|
||||
extern const unsigned long SIOCGRARP;
|
||||
extern const unsigned long SIOCGSTAMP;
|
||||
extern const unsigned long SIOCGSTAMPNS;
|
||||
extern const unsigned long SIOCPROTOPRIVATE;
|
||||
extern const unsigned long SIOCRTMSG;
|
||||
extern const unsigned long SIOCSARP;
|
||||
extern const unsigned long SIOCSIFADDR;
|
||||
extern const unsigned long SIOCSIFBR;
|
||||
extern const unsigned long SIOCSIFBRDADDR;
|
||||
extern const unsigned long SIOCSIFDSTADDR;
|
||||
extern const unsigned long SIOCSIFENCAP;
|
||||
extern const unsigned long SIOCSIFFLAGS;
|
||||
extern const unsigned long SIOCSIFHWADDR;
|
||||
extern const unsigned long SIOCSIFHWBROADCAST;
|
||||
extern const unsigned long SIOCSIFLINK;
|
||||
extern const unsigned long SIOCSIFMAP;
|
||||
extern const unsigned long SIOCSIFMEM;
|
||||
extern const unsigned long SIOCSIFMETRIC;
|
||||
extern const unsigned long SIOCSIFMTU;
|
||||
extern const unsigned long SIOCSIFNAME;
|
||||
extern const unsigned long SIOCSIFNETMASK;
|
||||
extern const unsigned long SIOCSIFPFLAGS;
|
||||
extern const unsigned long SIOCSIFSLAVE;
|
||||
extern const unsigned long SIOCSIFTXQLEN;
|
||||
extern const unsigned long SIOCSPGRP;
|
||||
extern const unsigned long SIOCSRARP;
|
||||
extern const unsigned long SIOGIFINDEX;
|
||||
|
||||
#define SIOCADDDLCI SIOCADDDLCI
|
||||
#define SIOCADDMULTI SIOCADDMULTI
|
||||
#define SIOCADDRT SIOCADDRT
|
||||
#define SIOCATMARK SIOCATMARK
|
||||
#define SIOCDARP SIOCDARP
|
||||
#define SIOCDELDLCI SIOCDELDLCI
|
||||
#define SIOCDELMULTI SIOCDELMULTI
|
||||
#define SIOCDELRT SIOCDELRT
|
||||
#define SIOCDEVPRIVATE SIOCDEVPRIVATE
|
||||
#define SIOCDIFADDR SIOCDIFADDR
|
||||
#define SIOCDRARP SIOCDRARP
|
||||
#define SIOCGARP SIOCGARP
|
||||
#define SIOCGIFADDR SIOCGIFADDR
|
||||
#define SIOCGIFBR SIOCGIFBR
|
||||
#define SIOCGIFBRDADDR SIOCGIFBRDADDR
|
||||
#define SIOCGIFCONF SIOCGIFCONF
|
||||
#define SIOCGIFCOUNT SIOCGIFCOUNT
|
||||
#define SIOCGIFDSTADDR SIOCGIFDSTADDR
|
||||
#define SIOCGIFENCAP SIOCGIFENCAP
|
||||
#define SIOCGIFFLAGS SIOCGIFFLAGS
|
||||
#define SIOCGIFHWADDR SIOCGIFHWADDR
|
||||
#define SIOCGIFINDEX SIOCGIFINDEX
|
||||
#define SIOCGIFMAP SIOCGIFMAP
|
||||
#define SIOCGIFMEM SIOCGIFMEM
|
||||
#define SIOCGIFMETRIC SIOCGIFMETRIC
|
||||
#define SIOCGIFMTU SIOCGIFMTU
|
||||
#define SIOCGIFNAME SIOCGIFNAME
|
||||
#define SIOCGIFNETMASK SIOCGIFNETMASK
|
||||
#define SIOCGIFPFLAGS SIOCGIFPFLAGS
|
||||
#define SIOCGIFSLAVE SIOCGIFSLAVE
|
||||
#define SIOCGIFTXQLEN SIOCGIFTXQLEN
|
||||
#define SIOCGPGRP SIOCGPGRP
|
||||
#define SIOCGRARP SIOCGRARP
|
||||
#define SIOCGSTAMP SIOCGSTAMP
|
||||
#define SIOCGSTAMPNS SIOCGSTAMPNS
|
||||
#define SIOCPROTOPRIVATE SIOCPROTOPRIVATE
|
||||
#define SIOCRTMSG SIOCRTMSG
|
||||
#define SIOCSARP SIOCSARP
|
||||
#define SIOCSIFADDR SIOCSIFADDR
|
||||
#define SIOCSIFBR SIOCSIFBR
|
||||
#define SIOCSIFBRDADDR SIOCSIFBRDADDR
|
||||
#define SIOCSIFDSTADDR SIOCSIFDSTADDR
|
||||
#define SIOCSIFENCAP SIOCSIFENCAP
|
||||
#define SIOCSIFFLAGS SIOCSIFFLAGS
|
||||
#define SIOCSIFHWADDR SIOCSIFHWADDR
|
||||
#define SIOCSIFHWBROADCAST SIOCSIFHWBROADCAST
|
||||
#define SIOCSIFLINK SIOCSIFLINK
|
||||
#define SIOCSIFMAP SIOCSIFMAP
|
||||
#define SIOCSIFMEM SIOCSIFMEM
|
||||
#define SIOCSIFMETRIC SIOCSIFMETRIC
|
||||
#define SIOCSIFMTU SIOCSIFMTU
|
||||
#define SIOCSIFNAME SIOCSIFNAME
|
||||
#define SIOCSIFNETMASK SIOCSIFNETMASK
|
||||
#define SIOCSIFPFLAGS SIOCSIFPFLAGS
|
||||
#define SIOCSIFSLAVE SIOCSIFSLAVE
|
||||
#define SIOCSIFTXQLEN SIOCSIFTXQLEN
|
||||
#define SIOCSPGRP SIOCSPGRP
|
||||
#define SIOCSRARP SIOCSRARP
|
||||
#define SIOGIFINDEX SIOGIFINDEX
|
||||
#define SIOCGIFCONF SIOCGIFCONF
|
||||
#define SIOCGIFADDR SIOCGIFADDR
|
||||
#define SIOCSIFADDR SIOCSIFADDR
|
||||
#define SIOCDIFADDR SIOCDIFADDR
|
||||
#define SIOCGIFBRDADDR SIOCGIFBRDADDR
|
||||
#define SIOCGIFNETMASK SIOCGIFNETMASK
|
||||
#define SIOCGIFFLAGS SIOCGIFFLAGS
|
||||
#define SIOCSIFFLAGS SIOCSIFFLAGS
|
||||
#define SIOCGIFMETRIC SIOCGIFMETRIC
|
||||
#define SIOCSIFMETRIC SIOCSIFMETRIC
|
||||
#define SIOCSIFBRDADDR SIOCSIFBRDADDR
|
||||
#define SIOCSIFNETMASK SIOCSIFNETMASK
|
||||
#define SIOCGIFDSTADDR SIOCGIFDSTADDR
|
||||
#define SIOCSIFDSTADDR SIOCSIFDSTADDR
|
||||
#define SIOCGIFMTU SIOCGIFMTU
|
||||
#define SIOCSIFMTU SIOCSIFMTU
|
||||
|
||||
#define SIOCGPGRP SIOCGPGRP
|
||||
#define SIOCSPGRP SIOCSPGRP
|
||||
|
||||
#define SIOCADDMULTI SIOCADDMULTI
|
||||
#define SIOCDELMULTI SIOCDELMULTI
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -155,73 +155,74 @@ extern const uint32_t CRTSCTS;
|
|||
#define FF1 FF1
|
||||
#define FF2 FF2
|
||||
|
||||
#define CLOCAL CLOCAL
|
||||
#define CREAD CREAD
|
||||
#define CS5 CS5
|
||||
#define CS6 CS6
|
||||
#define CS7 CS7
|
||||
#define CS8 CS8
|
||||
#define CSIZE CSIZE
|
||||
#define CSTOPB CSTOPB
|
||||
#define ECHO 8
|
||||
#define ECHOCTL ECHOCTL
|
||||
#define ECHOE ECHOE
|
||||
#define ECHOK ECHOK
|
||||
#define ECHOKE ECHOKE
|
||||
#define ECHONL ECHONL
|
||||
#define ECHOPRT ECHOPRT
|
||||
#define EXTPROC EXTPROC
|
||||
#define FLUSHO FLUSHO
|
||||
#define HUPCL HUPCL
|
||||
#define ICANON ICANON
|
||||
#define IEXTEN IEXTEN
|
||||
#define ISIG ISIG
|
||||
#define IUCLC IUCLC
|
||||
#define IUTF8 IUTF8
|
||||
#define IXOFF IXOFF
|
||||
#define IXON IXON
|
||||
#define NOFLSH NOFLSH
|
||||
#define OCRNL OCRNL
|
||||
#define OFDEL OFDEL
|
||||
#define OFILL OFILL
|
||||
#define OLCUC OLCUC
|
||||
#define ONLCR ONLCR
|
||||
#define ONLRET ONLRET
|
||||
#define ONOCR ONOCR
|
||||
#define PARENB PARENB
|
||||
#define PARODD PARODD
|
||||
#define PENDIN PENDIN
|
||||
#define TIOCCONS TIOCCONS
|
||||
#define TIOCGETD TIOCGETD
|
||||
#define TIOCGWINSZ TIOCGWINSZ
|
||||
#define TIOCNOTTY TIOCNOTTY
|
||||
#define TIOCNXCL TIOCNXCL
|
||||
#define TIOCOUTQ TIOCOUTQ
|
||||
#define TIOCSCTTY TIOCSCTTY
|
||||
#define TIOCSETD TIOCSETD
|
||||
#define TIOCSIG TIOCSIG
|
||||
#define TIOCSPGRP TIOCSPGRP
|
||||
#define TIOCSTI TIOCSTI
|
||||
#define TIOCSWINSZ TIOCSWINSZ
|
||||
#define TOSTOP TOSTOP
|
||||
#define VDISCARD VDISCARD
|
||||
#define VEOF VEOF
|
||||
#define VEOL VEOL
|
||||
#define VEOL2 VEOL2
|
||||
#define VERASE VERASE
|
||||
#define VINTR VINTR
|
||||
#define VKILL VKILL
|
||||
#define VLNEXT VLNEXT
|
||||
#define VMIN VMIN
|
||||
#define VQUIT VQUIT
|
||||
#define VREPRINT VREPRINT
|
||||
#define VSTART VSTART
|
||||
#define VSTOP VSTOP
|
||||
#define VSUSP VSUSP
|
||||
#define VSWTC VSWTC
|
||||
#define VTIME VTIME
|
||||
#define VWERASE VWERASE
|
||||
#define XCASE XCASE
|
||||
#define CLOCAL CLOCAL
|
||||
#define CREAD CREAD
|
||||
#define CS5 CS5
|
||||
#define CS6 CS6
|
||||
#define CS7 CS7
|
||||
#define CS8 CS8
|
||||
#define CSIZE CSIZE
|
||||
#define CSTOPB CSTOPB
|
||||
#define ECHO 8
|
||||
#define ECHOCTL ECHOCTL
|
||||
#define ECHOE ECHOE
|
||||
#define ECHOK ECHOK
|
||||
#define ECHOKE ECHOKE
|
||||
#define ECHONL ECHONL
|
||||
#define ECHOPRT ECHOPRT
|
||||
#define EXTPROC EXTPROC
|
||||
#define FLUSHO FLUSHO
|
||||
#define HUPCL HUPCL
|
||||
#define ICANON ICANON
|
||||
#define IEXTEN IEXTEN
|
||||
#define ISIG ISIG
|
||||
#define IUCLC IUCLC
|
||||
#define IUTF8 IUTF8
|
||||
#define IXOFF IXOFF
|
||||
#define IXON IXON
|
||||
#define NOFLSH NOFLSH
|
||||
#define OCRNL OCRNL
|
||||
#define OFDEL OFDEL
|
||||
#define OFILL OFILL
|
||||
#define OLCUC OLCUC
|
||||
#define ONLCR ONLCR
|
||||
#define ONLRET ONLRET
|
||||
#define ONOCR ONOCR
|
||||
#define PARENB PARENB
|
||||
#define PARODD PARODD
|
||||
#define PENDIN PENDIN
|
||||
#define TOSTOP TOSTOP
|
||||
#define VDISCARD VDISCARD
|
||||
#define VEOF VEOF
|
||||
#define VEOL VEOL
|
||||
#define VEOL2 VEOL2
|
||||
#define VERASE VERASE
|
||||
#define VINTR VINTR
|
||||
#define VKILL VKILL
|
||||
#define VLNEXT VLNEXT
|
||||
#define VMIN VMIN
|
||||
#define VQUIT VQUIT
|
||||
#define VREPRINT VREPRINT
|
||||
#define VSTART VSTART
|
||||
#define VSTOP VSTOP
|
||||
#define VSUSP VSUSP
|
||||
#define VSWTC VSWTC
|
||||
#define VTIME VTIME
|
||||
#define VWERASE VWERASE
|
||||
#define XCASE XCASE
|
||||
|
||||
/* terminal ioctls */
|
||||
#define TIOCGWINSZ TIOCGWINSZ /* get tty dimensions */
|
||||
#define TIOCSWINSZ TIOCSWINSZ /* set tty dimensions */
|
||||
#define TIOCCONS TIOCCONS /* redirect terminal */
|
||||
#define TIOCGETD TIOCGETD /* get line discipline */
|
||||
#define TIOCSETD TIOCSETD /* set line discipline */
|
||||
#define TIOCNOTTY TIOCNOTTY /* give up terminal */
|
||||
#define TIOCNXCL TIOCNXCL /* disable exclusive mode */
|
||||
#define TIOCOUTQ TIOCOUTQ /* bytes in output buffer */
|
||||
#define TIOCSCTTY TIOCSCTTY /* make controlling terminal */
|
||||
#define TIOCSIG TIOCSIG /* generate pty signal */
|
||||
#define TIOCSTI TIOCSTI /* insert fake tty input */
|
||||
|
||||
/* tcsetattr() */
|
||||
#define TCSANOW 0
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- 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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2023 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 │
|
||||
|
@ -16,14 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/intrin/bits.h"
|
||||
#include "libc/log/check.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/mem/gc.internal.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/ifconf.h"
|
||||
#include "libc/sock/struct/ifreq.h"
|
||||
|
@ -34,7 +33,7 @@
|
|||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(ioctl_siocgifconf, test) {
|
||||
TEST(siocgifconf, test) {
|
||||
size_t n;
|
||||
char *data;
|
||||
int socketfd;
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/pledge.internal.h"
|
||||
#include "libc/calls/struct/bpf.internal.h"
|
||||
#include "libc/calls/struct/filter.internal.h"
|
||||
|
|
|
@ -149,7 +149,7 @@ o/$(MODE)/test/libc/calls/zipread.com.zip.o: private \
|
|||
-B
|
||||
|
||||
# TODO(jart): Have pledge() support SIOCGIFCONF
|
||||
o/$(MODE)/test/libc/calls/ioctl_siocgifconf_test.com.runs: \
|
||||
o/$(MODE)/test/libc/calls/ioctl_test.com.runs: \
|
||||
private .PLEDGE =
|
||||
|
||||
o/$(MODE)/test/libc/calls/poll_test.com.runs: \
|
||||
|
|
2
third_party/finger/display.c
vendored
2
third_party/finger/display.c
vendored
|
@ -33,7 +33,7 @@
|
|||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
|
1
third_party/linenoise/linenoise.c
vendored
1
third_party/linenoise/linenoise.c
vendored
|
@ -129,7 +129,6 @@
|
|||
#include "third_party/linenoise/linenoise.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
|
2
third_party/lua/lunix.c
vendored
2
third_party/lua/lunix.c
vendored
|
@ -21,7 +21,6 @@
|
|||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/cp.internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/makedev.h"
|
||||
#include "libc/calls/pledge.h"
|
||||
#include "libc/calls/struct/bpf.internal.h"
|
||||
|
@ -100,6 +99,7 @@
|
|||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/sysv/consts/st.h"
|
||||
#include "libc/sysv/consts/tcp.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/sysv/consts/utime.h"
|
||||
#include "libc/sysv/consts/w.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
|
1
third_party/python/Modules/fcntlmodule.c
vendored
1
third_party/python/Modules/fcntlmodule.c
vendored
|
@ -6,7 +6,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
|
|
1
third_party/python/Modules/posixmodule.c
vendored
1
third_party/python/Modules/posixmodule.c
vendored
|
@ -9,7 +9,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/makedev.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
|
|
1
third_party/python/Modules/socketmodule.c
vendored
1
third_party/python/Modules/socketmodule.c
vendored
|
@ -6,7 +6,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "third_party/python/Modules/socketmodule.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/weirdtypes.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/dns/dns.h"
|
||||
|
|
7
third_party/python/Python/fileutils.c
vendored
7
third_party/python/Python/fileutils.c
vendored
|
@ -4,21 +4,20 @@
|
|||
│ Python 3 │
|
||||
│ https://docs.python.org/3/license.html │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "third_party/python/Include/fileutils.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/str/unicode.h"
|
||||
#include "libc/sysv/consts/f.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
#include "libc/sysv/consts/o.h"
|
||||
#include "libc/str/locale.h"
|
||||
#include "libc/str/unicode.h"
|
||||
#include "third_party/python/Include/bytesobject.h"
|
||||
#include "third_party/python/Include/ceval.h"
|
||||
#include "third_party/python/Include/fileutils.h"
|
||||
#include "third_party/python/Include/object.h"
|
||||
#include "third_party/python/Include/osdefs.h"
|
||||
#include "third_party/python/Include/pyerrors.h"
|
||||
|
|
1
third_party/quickjs/quickjs-libc.c
vendored
1
third_party/quickjs/quickjs-libc.c
vendored
|
@ -26,7 +26,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
|
1
third_party/sed/process.c
vendored
1
third_party/sed/process.c
vendored
|
@ -32,7 +32,6 @@
|
|||
* SUCH DAMAGE.
|
||||
*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
|
1
third_party/sqlite3/os_unix.c
vendored
1
third_party/sqlite3/os_unix.c
vendored
|
@ -117,7 +117,6 @@
|
|||
#endif
|
||||
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
|
|
1
third_party/unzip/ttyio.c
vendored
1
third_party/unzip/ttyio.c
vendored
|
@ -33,7 +33,6 @@
|
|||
#include "libc/calls/termios.h"
|
||||
#include "third_party/unzip/crypt.h"
|
||||
#include "libc/sysv/consts/termios.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "third_party/unzip/globals.h"
|
||||
|
|
2
third_party/zip/ttyio.c
vendored
2
third_party/zip/ttyio.c
vendored
|
@ -110,7 +110,6 @@
|
|||
|
||||
#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
|
@ -160,7 +159,6 @@
|
|||
# ifndef CMS_MVS
|
||||
# if (!defined(MINIX) && !defined(GOT_IOCTL_H))
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/sysv/consts/fd.h"
|
||||
#include "libc/sysv/consts/fio.h"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/copyfile.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/itimerval.h"
|
||||
#include "libc/calls/struct/rlimit.h"
|
||||
#include "libc/calls/struct/rusage.h"
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
│ 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 OUTPATH OF OR IN CONNECTION WITH THE USE OR │ │
|
||||
PERFORMANCE OF THIS SOFTWARE. │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/errno.h"
|
||||
|
@ -57,9 +57,48 @@ PERFORMANCE OF THIS SOFTWARE. │
|
|||
"copyright 2023 justine tunney\n" \
|
||||
"https://github.com/jart/cosmopolitan\n"
|
||||
|
||||
#define kIncludePrefix "include \""
|
||||
#define MANUAL \
|
||||
" -r o// -o OUTPUT INPUT...\n" \
|
||||
"\n" \
|
||||
"DESCRIPTION\n" \
|
||||
"\n" \
|
||||
" Generates makefile defining header dependencies.\n" \
|
||||
"\n" \
|
||||
" Includes look like this:\n" \
|
||||
"\n" \
|
||||
" - #include \"root/of/repository/foo.h\"\n" \
|
||||
" - .include \"root/of/repository/foo.inc\"\n" \
|
||||
"\n" \
|
||||
" They do NOT look like this:\n" \
|
||||
"\n" \
|
||||
" - #include <stdio.h>\n" \
|
||||
" - #include \"foo.h\"\n" \
|
||||
" - # include \"foo.h\"\n" \
|
||||
" - #include \"foo.h\"\n" \
|
||||
"\n" \
|
||||
" Your generated make code looks like this:\n" \
|
||||
"\n" \
|
||||
" o//package/foo.o: \\\n" \
|
||||
" package/foo.c \\\n" \
|
||||
" package/foo.h \\\n" \
|
||||
" package/bar.h\n" \
|
||||
" o//package/bar.o: \\\n" \
|
||||
" package/bar.c \\\n" \
|
||||
" package/bar.h\n" \
|
||||
"\n" \
|
||||
"FLAGS\n" \
|
||||
"\n" \
|
||||
" -h show usage\n" \
|
||||
" -o OUTPUT set output path\n" \
|
||||
" -r ROOT set build output prefix, e.g. o//\n" \
|
||||
"\n" \
|
||||
"ARGUMENTS\n" \
|
||||
"\n" \
|
||||
" OUTPUT shall be makefile code\n" \
|
||||
" INPUT should be source or @args.txt\n" \
|
||||
"\n"
|
||||
|
||||
const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
|
||||
#define kIncludePrefix "include \""
|
||||
|
||||
struct Source {
|
||||
unsigned hash;
|
||||
|
@ -87,6 +126,8 @@ struct Edges {
|
|||
struct Edge *p;
|
||||
};
|
||||
|
||||
static const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
|
||||
|
||||
static char *names;
|
||||
static unsigned counter;
|
||||
static const char *prog;
|
||||
|
@ -295,24 +336,7 @@ static void LoadRelationships(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
static wontreturn void ShowUsage(int rc, int fd) {
|
||||
tinyprint(fd, VERSION,
|
||||
"\n"
|
||||
"USAGE\n"
|
||||
"\n",
|
||||
" ", prog, " -r o// -o OUTPUT INPUT...\n",
|
||||
"\n"
|
||||
"FLAGS\n"
|
||||
"\n"
|
||||
" -h show usage\n"
|
||||
" -o OUTPUT set output path\n"
|
||||
" -r ROOT set build output prefix, e.g. o//\n"
|
||||
"\n"
|
||||
"ARGUMENTS\n"
|
||||
"\n"
|
||||
" OUTPUT shall be makefile code\n"
|
||||
" INPUT should be source or @args.txt\n"
|
||||
"\n",
|
||||
NULL);
|
||||
tinyprint(fd, VERSION, "\nUSAGE\n\n ", prog, MANUAL, NULL);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/pledge.h"
|
||||
#include "libc/calls/struct/dirent.h"
|
||||
#include "libc/calls/struct/flock.h"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/scale/scale.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "dsp/tty/itoa8.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/scale/cdecimate2xuint8x8.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/scale/scale.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/termios.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "dsp/scale/cdecimate2xuint8x8.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/sigaction.h"
|
||||
#include "libc/calls/struct/siginfo.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "dsp/tty/tty.h"
|
||||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "dsp/tty/quant.h"
|
||||
#include "dsp/tty/tty.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/ioctl.h"
|
||||
#include "libc/calls/struct/framebufferfixedscreeninfo.h"
|
||||
#include "libc/calls/struct/framebuffervirtualscreeninfo.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
|
|
Loading…
Add table
Reference in a new issue