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:
Justine Tunney 2023-07-11 04:29:33 -07:00
parent a1b1fdd1a4
commit 1ee2e89326
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
53 changed files with 1155 additions and 1255 deletions

View file

@ -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.elf: o/$(MODE)/ape/ape.elf.dbg
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
o/$(MODE)/ape/ape.elf.dbg: private \ APE_LOADER_LDFLAGS = \
LDFLAGS += \ -static \
-z common-page-size=0x10 \ -no-pie \
-z max-page-size=0x10 -nostdlib \
--no-dynamic-linker \
-zcommon-page-size=0x1000 \
-zmax-page-size=0x1000
o/$(MODE)/ape/ape.elf.dbg: \ o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/loader.o \ o/$(MODE)/ape/loader.o \
o/$(MODE)/ape/loader-elf.o \ o/$(MODE)/ape/loader-elf.o \
ape/loader.lds 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/ape.macho.dbg: \
o/$(MODE)/ape/loader-xnu.o \ o/$(MODE)/ape/loader-xnu.o \
o/$(MODE)/ape/loader-macho.o \ o/$(MODE)/ape/loader-macho.o \
ape/loader.lds 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 .PHONY: o/$(MODE)/ape
o/$(MODE)/ape: $(APE_CHECKS) \ o/$(MODE)/ape: $(APE_CHECKS) \

View file

@ -12,13 +12,8 @@ echo "Author: Justine Tunney <jtunney@gmail.com>" >&2
################################################################################ ################################################################################
# INSTALL APE LOADER SYSTEMWIDE # INSTALL APE LOADER SYSTEMWIDE
if [ -f o/depend ]; then if [ -f o/depend ] && make -j8 o//ape; then
# mkdeps.com build was successfully run so assume we can build echo "successfully recompiled ape loader" >&2
echo >&2
echo "recompiling ape loader" >&2
echo "running: make -j8 o//ape" >&2
make -j8 o//ape || exit
echo "done" >&2
elif [ -d build/bootstrap ]; then elif [ -d build/bootstrap ]; then
# if make isn't being used then it's unlikely the user changed the sources # 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 # in that case the prebuilt binaries should be completely up-to-date

View file

@ -77,12 +77,18 @@
* @note this can probably be used as a binfmt_misc interpreter * @note this can probably be used as a binfmt_misc interpreter
*/ */
#define PAGE_SIZE 4096
#define NULL_PAGE 2097152
#define LINUX 1 #define LINUX 1
#define XNU 8 #define XNU 8
#define OPENBSD 16 #define OPENBSD 16
#define FREEBSD 32 #define FREEBSD 32
#define NETBSD 64 #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 SupportsLinux() (SUPPORT_VECTOR & LINUX)
#define SupportsXnu() (SUPPORT_VECTOR & XNU) #define SupportsXnu() (SUPPORT_VECTOR & XNU)
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD) #define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
@ -103,29 +109,29 @@
#define MAP_PRIVATE 2 #define MAP_PRIVATE 2
#define MAP_FIXED 16 #define MAP_FIXED 16
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096) #define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
#define AT_EXECFN_LINUX 31
#define AT_EXECFN_NETBSD 2014
#define ELFCLASS32 1 #define ELFCLASS32 1
#define ELFDATA2LSB 1 #define ELFDATA2LSB 1
#define EM_NEXGEN32E 62 #define EM_NEXGEN32E 62
#define ET_EXEC 2 #define ET_EXEC 2
#define PT_LOAD 1 #define PT_LOAD 1
#define PT_DYNAMIC 2 #define PT_DYNAMIC 2
#define PT_INTERP 3
#define EI_CLASS 4 #define EI_CLASS 4
#define EI_DATA 5 #define EI_DATA 5
#define PF_X 1 #define PF_X 1
#define PF_W 2 #define PF_W 2
#define PF_R 4 #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 X_OK 1
#define XCR0_SSE 2 #define XCR0_SSE 2
#define XCR0_AVX 4 #define XCR0_AVX 4
#define PR_SET_MM 35 #define PR_SET_MM 35
#define PR_SET_MM_EXE_FILE 13 #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) \ #define Read32(S) \
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \ ((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000) (unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
@ -190,16 +196,14 @@ struct ApeLoader {
union ElfEhdrBuf ehdr; union ElfEhdrBuf ehdr;
union ElfPhdrBuf phdr; union ElfPhdrBuf phdr;
struct PathSearcher ps; struct PathSearcher ps;
char path[1024];
}; };
long SystemCall(long arg1, // long SystemCall(long arg1, long arg2, long arg3, long arg4, long arg5,
long arg2, // long arg6, long arg7, long magi);
long arg3, //
long arg4, // extern char __executable_start[];
long arg5, // extern char _end[];
long arg6, //
long arg7, //
long magi);
static int ToLower(int c) { static int ToLower(int c) {
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : 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()) { } else if (IsFreebsd()) {
magi = 0x1db; magi = 0x1db;
} else if (IsOpenbsd()) { } else if (IsOpenbsd()) {
magi = 0x0a9; // OpenBSD v7.3+ magi = 0x0a9; /* OpenBSD v7.3+ */
} else if (IsNetbsd()) { } else if (IsNetbsd()) {
magi = 0x0ad; magi = 0x0ad;
} else { } else {
@ -337,6 +341,11 @@ static int Open(const char *path, int flags, int mode, int os) {
(IsLinux() ? 2 : 5) | (IsXnu() ? 0x2000000 : 0)); (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, static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
long off, int os) { long off, int os) {
long magi; long magi;
@ -347,7 +356,7 @@ static long Mmap(void *addr, unsigned long size, int prot, int flags, int fd,
} else if (IsFreebsd()) { } else if (IsFreebsd()) {
magi = 477; magi = 477;
} else if (IsOpenbsd()) { } else if (IsOpenbsd()) {
magi = 49; // OpenBSD v7.3+ magi = 49; /* OpenBSD v7.3+ */
} else if (IsNetbsd()) { } else if (IsNetbsd()) {
magi = 197; magi = 197;
} else { } else {
@ -480,15 +489,26 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
long *sp, struct ElfEhdr *e, long *sp, struct ElfEhdr *e,
struct ElfPhdr *p) { struct ElfPhdr *p) {
long rc; long rc;
int prot, flags; int prot;
int flags;
int found_code;
int found_entry;
long code, codesize; long code, codesize;
unsigned long a, b, i; unsigned long a, b, c, d, i, j;
/* load elf */
code = 0; code = 0;
codesize = 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) { 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) { if (p[i].p_type != PT_LOAD) {
continue; continue;
@ -496,12 +516,39 @@ __attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
if (!p[i].p_memsz) { if (!p[i].p_memsz) {
continue; continue;
} }
if (p[i].p_vaddr & 4095) { if (p[i].p_filesz > p[i].p_memsz) {
Pexit(os, exe, 0, "APE phdr addr must be 4096-aligned"); Pexit(os, exe, 0, "ELF phdr filesz exceeds memsz");
} }
if (p[i].p_offset & 4095) { if ((p[i].p_vaddr & (PAGE_SIZE - 1)) != (p[i].p_offset & (PAGE_SIZE - 1))) {
Pexit(os, exe, 0, "APE phdr offset must be 4096-aligned"); 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; prot = 0;
flags = MAP_FIXED | MAP_PRIVATE; flags = MAP_FIXED | MAP_PRIVATE;
if (p[i].p_flags & PF_R) { 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) { if (p[i].p_flags & PF_X) {
prot |= PROT_EXEC; prot |= PROT_EXEC;
code = p[i].p_vaddr; if (!found_code) {
codesize = p[i].p_filesz; 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 (p[i].p_filesz) {
if ((rc = Mmap((void *)p[i].p_vaddr, p[i].p_filesz, prot, flags, fd, void *addr;
p[i].p_offset, os)) < 0) { unsigned long size;
Pexit(os, exe, rc, "image mmap"); 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))) { addr = (void *)(p[i].p_vaddr & -PAGE_SIZE);
MemSet((void *)(p[i].p_vaddr + p[i].p_filesz), 0, a); 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))) { /* allocate extra bss */
if ((rc = Mmap((void *)p[i].p_vaddr + a, b - a, prot, a = p[i].p_vaddr + p[i].p_filesz;
flags | MAP_ANONYMOUS, -1, 0, os)) < 0) { a = (a + (PAGE_SIZE - 1)) & -PAGE_SIZE;
Pexit(os, exe, rc, "bss mmap"); 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); Close(fd, os);
Msyscall(code, codesize, os); Msyscall(code, codesize, os);
// we clear all the general registers we can to have some wiggle room /* 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 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 to clear the xmm registers since the ape loader should be compiled
// with the -mgeneral-regs-only flag. with the -mgeneral-regs-only flag. */
asm volatile("xor\t%%eax,%%eax\n\t" asm volatile("xor\t%%eax,%%eax\n\t"
"xor\t%%r8d,%%r8d\n\t" "xor\t%%r8d,%%r8d\n\t"
"xor\t%%r9d,%%r9d\n\t" "xor\t%%r9d,%%r9d\n\t"
"xor\t%%r10d,%%r10d\n\t" "xor\t%%r10d,%%r10d\n\t"
"xor\t%%r11d,%%r11d\n\t" "xor\t%%r11d,%%r11d\n\t"
"xor\t%%ebx,%%ebx\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%%r12d,%%r12d\n\t" /* netbsd doesnt't clear this */
"xor\t%%r13d,%%r13d\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%%r14d,%%r14d\n\t" /* netbsd doesnt't clear this */
"xor\t%%r15d,%%r15d\n\t" // netbsd doesnt't clear this "xor\t%%r15d,%%r15d\n\t" /* netbsd doesnt't clear this */
"mov\t%%rdx,%%rsp\n\t" "mov\t%%rdx,%%rsp\n\t"
"xor\t%%edx,%%edx\n\t" "xor\t%%edx,%%edx\n\t"
"push\t%%rsi\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, static void TryElf(struct ApeLoader *M, const char *exe, int fd, long *sp,
int os) { long *auxv, int os) {
unsigned size; unsigned size = M->ehdr.ehdr.e_phnum;
if (Read32(M->ehdr.buf) == Read32("\177ELF") && // if (Read32(M->ehdr.buf) == Read32("\177ELF") &&
M->ehdr.ehdr.e_type == ET_EXEC && // M->ehdr.ehdr.e_type == ET_EXEC &&
M->ehdr.ehdr.e_machine == EM_NEXGEN32E && // M->ehdr.ehdr.e_machine == EM_NEXGEN32E &&
M->ehdr.ehdr.e_ident[EI_CLASS] != ELFCLASS32 && // M->ehdr.ehdr.e_ident[EI_CLASS] != ELFCLASS32 &&
M->ehdr.ehdr.e_phentsize >= sizeof(M->phdr.phdr) && // M->ehdr.ehdr.e_phentsize >= sizeof(M->phdr.phdr) &&
(size = (unsigned)M->ehdr.ehdr.e_phnum * M->ehdr.ehdr.e_phentsize) <= (size *= M->ehdr.ehdr.e_phentsize) <= sizeof(M->phdr.buf) &&
sizeof(M->phdr.buf) &&
Pread(fd, M->phdr.buf, size, M->ehdr.ehdr.e_phoff, os) == size) { 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); 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; long *auxv, *ap, *ew;
char *p, *exe, *prog, **argv, **envp; char *p, *exe, *prog, **argv, **envp;
// detect freebsd /* detect freebsd */
if (SupportsXnu() && dl == XNU) { if (SupportsXnu() && dl == XNU) {
os = XNU; os = XNU;
} else if (SupportsFreebsd() && di) { } else if (SupportsFreebsd() && di) {
@ -598,7 +688,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
os = 0; os = 0;
} }
// extract arguments /* extract arguments */
argc = *sp; argc = *sp;
argv = (char **)(sp + 1); argv = (char **)(sp + 1);
envp = (char **)(sp + 1 + argc + 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]) { if (SupportsOpenbsd() && !os && !auxv[0]) {
os = OPENBSD; os = OPENBSD;
} }
// detect netbsd and find end of words /* detect netbsd and find end of words */
for (ap = auxv; ap[0]; ap += 2) { for (ap = auxv; ap[0]; ap += 2) {
if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) { if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
os = NETBSD; os = NETBSD;
@ -622,23 +712,23 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
} }
ew = ap + 1; ew = ap + 1;
// allocate loader memory /* allocate loader memory */
n = sizeof(*M) / sizeof(long); n = sizeof(*M) / sizeof(long);
MemMove(sp - n, sp, (char *)ew - (char *)sp); MemMove(sp - n, sp, (char *)ew - (char *)sp);
sp -= n, argv -= n, envp -= n, auxv -= n; sp -= n, argv -= n, envp -= n, auxv -= n;
M = (struct ApeLoader *)(ew - n); M = (struct ApeLoader *)(ew - n);
// default operating system /* default operating system */
if (!os) { if (!os) {
os = LINUX; 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 (argc >= 3 && !StrCmp(argv[1], "-")) {
// if the first argument is a hyphen then we give the user the /* if the first argument is a hyphen then we give the user the
// power to change argv[0] or omit it entirely. most operating 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 systems don't permit the omission of argv[0] but we do, b/c
// it's specified by ANSI X3.159-1988. it's specified by ANSI X3.159-1988. */
prog = (char *)sp[3]; prog = (char *)sp[3];
argc = sp[3] = sp[0] - 3; argc = sp[3] = sp[0] - 3;
argv = (char **)((sp += 3) + 1); argv = (char **)((sp += 3) + 1);
@ -646,7 +736,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
Print(os, 2, Print(os, 2,
"usage: ape PROG [ARGV1,ARGV2,...]\n" "usage: ape PROG [ARGV1,ARGV2,...]\n"
" ape - PROG [ARGV0,ARGV1,...]\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" "copyright 2022 justine alexandra roberts tunney\n"
"https://justine.lol/ape.html\n", "https://justine.lol/ape.html\n",
0l); 0l);
@ -657,7 +747,7 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
argv = (char **)((sp += 1) + 1); 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")))) { if (!(exe = Commandv(&M->ps, os, prog, GetEnv(envp, "PATH")))) {
Pexit(os, prog, 0, "not found (maybe chmod +x)"); Pexit(os, prog, 0, "not found (maybe chmod +x)");
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) { } 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"); 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])) { if (argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) {
argv[0] = exe; argv[0] = exe;
} }
// ape intended behavior /* ape intended behavior
// 1. if file is a native executable, try to run it natively 1. if file is a native executable, try to run it natively
// 2. if ape, will scan shell script for elf printf statements 2. if ape, will scan shell script for elf printf statements
// 3. shell script may have multiple lines producing elf headers 3. shell script may have multiple lines producing elf headers
// 4. all elf printf lines must exist in the first 4096 bytes of file 4. all elf printf lines must exist in the first 4096 bytes of file
// 5. elf program headers may appear anywhere in the binary 5. elf program headers may appear anywhere in the binary */
if ((IsXnu() && Read32(M->ehdr.buf) == 0xFEEDFACE + 1) || if ((IsXnu() && Read32(M->ehdr.buf) == 0xFEEDFACE + 1) ||
(!IsXnu() && Read32(M->ehdr.buf) == Read32("\177ELF"))) { (!IsXnu() && Read32(M->ehdr.buf) == Read32("\177ELF"))) {
Close(fd, os); Close(fd, os);
@ -708,10 +798,10 @@ __attribute__((__noreturn__)) void ApeLoader(long di, long *sp, char dl) {
M->ehdr.buf[i++] = c; M->ehdr.buf[i++] = c;
} }
if (i >= sizeof(M->ehdr.ehdr)) { 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"); Pexit(os, exe, 0, "Not an acceptable APE/ELF executable for x86-64");
} }

View file

@ -19,7 +19,8 @@
ENTRY(_start) ENTRY(_start)
SECTIONS { SECTIONS {
. = 0x200000; . = 0x7fff0000;
__executable_start = .;
.rodata : { .rodata : {
KEEP(*(.head)) KEEP(*(.head))
*(.rodata .rodata.*) *(.rodata .rodata.*)
@ -29,6 +30,7 @@ SECTIONS {
text = .; text = .;
*(.text) *(.text)
} }
_end = .;
/DISCARD/ : { /DISCARD/ : {
*(.*) *(.*)
} }

Binary file not shown.

Binary file not shown.

View file

@ -8,7 +8,6 @@
*/ */
#endif #endif
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"

View file

@ -30,7 +30,6 @@
SUCH DAMAGE. SUCH DAMAGE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"

View file

@ -9,7 +9,6 @@
#endif #endif
#include "dsp/tty/tty.h" #include "dsp/tty/tty.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "libc/errno.h" #include "libc/errno.h"

View file

@ -114,6 +114,7 @@ int getpriority(int, unsigned);
int getresgid(unsigned *, unsigned *, unsigned *); int getresgid(unsigned *, unsigned *, unsigned *);
int getresuid(unsigned *, unsigned *, unsigned *); int getresuid(unsigned *, unsigned *, unsigned *);
int getsid(int) nosideeffect libcesque; int getsid(int) nosideeffect libcesque;
int ioctl(int, unsigned long, ...);
int ioprio_get(int, int); int ioprio_get(int, int);
int ioprio_set(int, int, int); int ioprio_set(int, int, int);
int issetugid(void); int issetugid(void);

View file

@ -136,8 +136,6 @@ o/$(MODE)/libc/calls/mkntenvblock.o: private \
# we must segregate codegen because: # we must segregate codegen because:
# file contains multiple independently linkable apis # file contains multiple independently linkable apis
o/$(MODE)/libc/calls/ioctl-siocgifconf.o \
o/$(MODE)/libc/calls/ioctl-siocgifconf-nt.o: private \
COPTS += \ COPTS += \
-ffunction-sections \ -ffunction-sections \
-fdata-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 # va_arg codegen is very bloated in default mode
o//libc/calls/open.o \ o//libc/calls/open.o \
o//libc/calls/openat.o \ o//libc/calls/openat.o \
o//libc/calls/prctl.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 \
CFLAGS += \ CFLAGS += \
-Os -Os

View file

@ -16,27 +16,686 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#ifdef __STRICT_ANSI__ #include "libc/assert.h"
#undef __STRICT_ANSI__ #include "libc/calls/internal.h"
#endif #include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/termios.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/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 * @restartable
* @vforksafe * @vforksafe
*/ */
int(ioctl)(int fd, uint64_t request, ...) { int ioctl(int fd, unsigned long request, ...) {
int rc;
void *arg; void *arg;
va_list va; va_list va;
va_start(va, request); va_start(va, request);
arg = va_arg(va, void *); arg = va_arg(va, void *);
va_end(va); va_end(va);
if (request == TIOCGWINSZ) return tcgetwinsize(fd, arg); if (request == FIONBIO) {
if (request == TIOCSWINSZ) return tcsetwinsize(fd, arg); rc = ioctl_default(fd, request, arg);
return __IOCTL_DISPATCH(EQUAL, -1, 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;
} }

View file

@ -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_ */

View file

@ -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();
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -19,7 +19,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/blockcancel.internal.h" #include "libc/calls/blockcancel.internal.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/metatermios.internal.h" #include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/struct/winsize.internal.h" #include "libc/calls/struct/winsize.internal.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/metatermios.internal.h" #include "libc/calls/struct/metatermios.internal.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"

View file

@ -1,7 +1,6 @@
#ifndef LIBC_ISYSTEM_SYS_IOCTL_H_ #ifndef LIBC_ISYSTEM_SYS_IOCTL_H_
#define LIBC_ISYSTEM_SYS_IOCTL_H_ #define LIBC_ISYSTEM_SYS_IOCTL_H_
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/fio.h"

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/syscall-sysv.internal.h" #include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/intrin/strace.internal.h" #include "libc/intrin/strace.internal.h"

View file

@ -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_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_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 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_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_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 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_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 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 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_MAXFD -1 -1 -1 -1 -1 -1 11 -1 #
syscon fcntl F_NOTIFY 0x0402 0x0402 -1 -1 -1 -1 -1 -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 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_SETLEASE 0x0400 0x0400 -1 106 -1 -1 -1 -1
syscon fcntl F_GETLEASE 0x0401 0x0401 -1 107 -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 # 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 # 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 # 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 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 # 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 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 sio SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus syscon ioctl FIOASYNC 0x5452 0x5452 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d 0x8004667d # BSD-The New Technology consensus
syscon sio SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd 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 sio SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus syscon ioctl FIOCLEX 0x5451 0x5451 0x20006601 0x20006601 0x20006601 0x20006601 0x20006601 0x5451 # sets "close on exec" on file descriptor the fast way; faked nt
syscon sio SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0 # bsd consensus syscon ioctl FIONCLEX 0x5450 0x5450 0x20006602 0x20006602 0x20006602 0x20006602 0x20006602 0x5450 # clears "close on exec" on file descriptor the fast way; faked nt
syscon sio SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0 # bsd consensus #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 sio SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0 # bsd consensus #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 sio SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0 # bsd consensus syscon ioctl SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0
syscon sio SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0 # bsd consensus syscon ioctl SIOCATMARK 0x8905 0x8905 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 0x40047307 # use sockatmark(); determines if oob is available; bsd consensus
syscon sio SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0 # bsd consensus syscon ioctl SIOCADDMULTI 0x8931 0x8931 0x80206931 0x80206931 0x80206931 0x80206931 0x80206931 0 # bsd consensus
syscon sio SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0 # bsd consensus syscon ioctl SIOCDELMULTI 0x8932 0x8932 0x80206932 0x80206932 0x80206932 0x80206932 0x80206932 0 # bsd consensus
syscon sio SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0 # bsd consensus syscon ioctl SIOCDIFADDR 0x8936 0x8936 0x80206919 0x80206919 0x80206919 0x80206919 0x80206919 0 # bsd consensus
syscon sio SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0 # bsd consensus syscon ioctl SIOCGIFADDR 0x8915 0x8915 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0xc0206921 0 # bsd consensus
syscon sio SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0 # bsd consensus syscon ioctl SIOCGIFBRDADDR 0x8919 0x8919 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0xc0206923 0 # bsd consensus
syscon sio SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0 # bsd consensus syscon ioctl SIOCGIFDSTADDR 0x8917 0x8917 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0xc0206922 0 # bsd consensus
syscon sio SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0 # bsd consensus syscon ioctl SIOCGIFFLAGS 0x8913 0x8913 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0xc0206911 0 # bsd consensus
syscon sio SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0 # bsd consensus syscon ioctl SIOCGIFMETRIC 0x891d 0x891d 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0xc0206917 0 # bsd consensus
syscon sio SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0 # bsd consensus syscon ioctl SIOCGIFNETMASK 0x891b 0x891b 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0xc0206925 0 # bsd consensus
syscon sio SIOCGIFCONF 0x8912 0x8912 0xc00c6924 0xc00c6924 0xc0106924 0xc0106924 0xc0106924 0 syscon ioctl SIOCGPGRP 0x8904 0x8904 0x40047309 0x40047309 0x40047309 0x40047309 0x40047309 0 # bsd consensus
syscon sio SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0 syscon ioctl SIOCSIFADDR 0x8916 0x8916 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0x8020690c 0 # bsd consensus
syscon sio SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0 syscon ioctl SIOCSIFBRDADDR 0x891a 0x891a 0x80206913 0x80206913 0x80206913 0x80206913 0x80206913 0 # bsd consensus
syscon sio SIOCGIFINDEX 0x8933 0x8933 0 0 0xc0206920 0 0 0 syscon ioctl SIOCSIFDSTADDR 0x8918 0x8918 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0x8020690e 0 # bsd consensus
syscon sio SIOCSIFNAME 0x8923 0x8923 0 0 0x80206928 0 0 0 syscon ioctl SIOCSIFFLAGS 0x8914 0x8914 0x80206910 0x80206910 0x80206910 0x80206910 0x80206910 0 # bsd consensus
syscon sio SIOCADDDLCI 0x8980 0x8980 0 0 0 0 0 0 syscon ioctl SIOCSIFMETRIC 0x891e 0x891e 0x80206918 0x80206918 0x80206918 0x80206918 0x80206918 0 # bsd consensus
syscon sio SIOCADDRT 0x890b 0x890b 0 0 0 0 0 0 syscon ioctl SIOCSIFNETMASK 0x891c 0x891c 0x80206916 0x80206916 0x80206916 0x80206916 0x80206916 0 # bsd consensus
syscon sio SIOCDARP 0x8953 0x8953 0 0 0 0 0 0 syscon ioctl SIOCSPGRP 0x8902 0x8902 0x80047308 0x80047308 0x80047308 0x80047308 0x80047308 0 # bsd consensus
syscon sio SIOCDELDLCI 0x8981 0x8981 0 0 0 0 0 0 syscon ioctl SIOCGIFMTU 0x8921 0x8921 0xc0206933 0xc0206933 0xc0206933 0xc020697e 0xc020697e 0
syscon sio SIOCDELRT 0x890c 0x890c 0 0 0 0 0 0 syscon ioctl SIOCSIFMTU 0x8922 0x8922 0x80206934 0x80206934 0x80206934 0x8020697f 0x8020697f 0
syscon sio SIOCDEVPRIVATE 0x89f0 0x89f0 0 0 0 0 0 0
syscon sio SIOCDRARP 0x8960 0x8960 0 0 0 0 0 0 syscon ioctl SIOCGIFINDEX 0x8933 0x8933 0 0 0xc0206920 0 0 0
syscon sio SIOCGARP 0x8954 0x8954 0 0 0 0 0 0 syscon ioctl SIOCSIFNAME 0x8923 0x8923 0 0 0x80206928 0 0 0
syscon sio SIOCGIFBR 0x8940 0x8940 0 0 0 0 0 0 syscon ioctl SIOCADDDLCI 0x8980 0x8980 0 0 0 0 0 0
syscon sio SIOCGIFCOUNT 0x8938 0x8938 0 0 0 0 0 0 syscon ioctl SIOCADDRT 0x890b 0x890b 0 0 0 0 0 0
syscon sio SIOCGIFENCAP 0x8925 0x8925 0 0 0 0 0 0 syscon ioctl SIOCDARP 0x8953 0x8953 0 0 0 0 0 0
syscon sio SIOCGIFHWADDR 0x8927 0x8927 0 0 0 0 0 0 syscon ioctl SIOCDELDLCI 0x8981 0x8981 0 0 0 0 0 0
syscon sio SIOCGIFMAP 0x8970 0x8970 0 0 0 0 0 0 syscon ioctl SIOCDELRT 0x890c 0x890c 0 0 0 0 0 0
syscon sio SIOCGIFMEM 0x891f 0x891f 0 0 0 0 0 0 syscon ioctl SIOCDEVPRIVATE 0x89f0 0x89f0 0 0 0 0 0 0
syscon sio SIOCGIFNAME 0x8910 0x8910 0 0 0 0 0 0 syscon ioctl SIOCDRARP 0x8960 0x8960 0 0 0 0 0 0
syscon sio SIOCGIFPFLAGS 0x8935 0x8935 0 0 0 0 0 0 syscon ioctl SIOCGARP 0x8954 0x8954 0 0 0 0 0 0
syscon sio SIOCGIFSLAVE 0x8929 0x8929 0 0 0 0 0 0 syscon ioctl SIOCGIFBR 0x8940 0x8940 0 0 0 0 0 0
syscon sio SIOCGIFTXQLEN 0x8942 0x8942 0 0 0 0 0 0 syscon ioctl SIOCGIFCOUNT 0x8938 0x8938 0 0 0 0 0 0
syscon sio SIOCGRARP 0x8961 0x8961 0 0 0 0 0 0 syscon ioctl SIOCGIFENCAP 0x8925 0x8925 0 0 0 0 0 0
syscon sio SIOCGSTAMP 0x8906 0x8906 0 0 0 0 0 0 syscon ioctl SIOCGIFHWADDR 0x8927 0x8927 0 0 0 0 0 0
syscon sio SIOCGSTAMPNS 0x8907 0x8907 0 0 0 0 0 0 syscon ioctl SIOCGIFMAP 0x8970 0x8970 0 0 0 0 0 0
syscon sio SIOCPROTOPRIVATE 0x89e0 0x89e0 0 0 0 0 0 0 syscon ioctl SIOCGIFMEM 0x891f 0x891f 0 0 0 0 0 0
syscon sio SIOCRTMSG 0x890d 0x890d 0 0 0 0 0 0 syscon ioctl SIOCGIFNAME 0x8910 0x8910 0 0 0 0 0 0
syscon sio SIOCSARP 0x8955 0x8955 0 0 0 0 0 0 syscon ioctl SIOCGIFPFLAGS 0x8935 0x8935 0 0 0 0 0 0
syscon sio SIOCSIFBR 0x8941 0x8941 0 0 0 0 0 0 syscon ioctl SIOCGIFSLAVE 0x8929 0x8929 0 0 0 0 0 0
syscon sio SIOCSIFENCAP 0x8926 0x8926 0 0 0 0 0 0 syscon ioctl SIOCGIFTXQLEN 0x8942 0x8942 0 0 0 0 0 0
syscon sio SIOCSIFHWADDR 0x8924 0x8924 0 0 0 0 0 0 syscon ioctl SIOCGRARP 0x8961 0x8961 0 0 0 0 0 0
syscon sio SIOCSIFHWBROADCAST 0x8937 0x8937 0 0 0 0 0 0 syscon ioctl SIOCGSTAMP 0x8906 0x8906 0 0 0 0 0 0
syscon sio SIOCSIFLINK 0x8911 0x8911 0 0 0 0 0 0 syscon ioctl SIOCGSTAMPNS 0x8907 0x8907 0 0 0 0 0 0
syscon sio SIOCSIFMAP 0x8971 0x8971 0 0 0 0 0 0 syscon ioctl SIOCPROTOPRIVATE 0x89e0 0x89e0 0 0 0 0 0 0
syscon sio SIOCSIFMEM 0x8920 0x8920 0 0 0 0 0 0 syscon ioctl SIOCRTMSG 0x890d 0x890d 0 0 0 0 0 0
syscon sio SIOCSIFPFLAGS 0x8934 0x8934 0 0 0 0 0 0 syscon ioctl SIOCSARP 0x8955 0x8955 0 0 0 0 0 0
syscon sio SIOCSIFSLAVE 0x8930 0x8930 0 0 0 0 0 0 syscon ioctl SIOCSIFBR 0x8941 0x8941 0 0 0 0 0 0
syscon sio SIOCSIFTXQLEN 0x8943 0x8943 0 0 0 0 0 0 syscon ioctl SIOCSIFENCAP 0x8926 0x8926 0 0 0 0 0 0
syscon sio SIOCSRARP 0x8962 0x8962 0 0 0 0 0 0 syscon ioctl SIOCSIFHWADDR 0x8924 0x8924 0 0 0 0 0 0
syscon sio SIOGIFINDEX 0x8933 0x8933 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 # socket() address families
# #

View file

@ -3,6 +3,11 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ 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_BARRIERFSYNC;
extern const int F_DUPFD; extern const int F_DUPFD;
extern const int F_DUPFD_CLOEXEC; extern const int F_DUPFD_CLOEXEC;
@ -42,34 +47,28 @@ extern const int F_WRLCK;
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#define F_DUPFD 0 /*
#define F_GETFD 1 * portable fcntl() commands
#define F_SETFD 2 */
#define F_GETFL 3 #define F_DUPFD 0
#define F_SETFL 4 #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_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_ */ #endif /* COSMOPOLITAN_LIBC_SYSV_CONSTS_F_H_ */

View file

@ -3,126 +3,88 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
extern const uint64_t SIOCADDDLCI; extern const unsigned long SIOCADDDLCI;
extern const uint64_t SIOCADDMULTI; extern const unsigned long SIOCADDMULTI;
extern const uint64_t SIOCADDRT; extern const unsigned long SIOCADDRT;
extern const uint64_t SIOCATMARK; extern const unsigned long SIOCATMARK; /* use sockatmark() */
extern const uint64_t SIOCDARP; extern const unsigned long SIOCDARP;
extern const uint64_t SIOCDELDLCI; extern const unsigned long SIOCDELDLCI;
extern const uint64_t SIOCDELMULTI; extern const unsigned long SIOCDELMULTI;
extern const uint64_t SIOCDELRT; extern const unsigned long SIOCDELRT;
extern const uint64_t SIOCDEVPRIVATE; extern const unsigned long SIOCDEVPRIVATE;
extern const uint64_t SIOCDIFADDR; extern const unsigned long SIOCDIFADDR;
extern const uint64_t SIOCDRARP; extern const unsigned long SIOCDRARP;
extern const uint64_t SIOCGARP; extern const unsigned long SIOCGARP;
extern const uint64_t SIOCGIFADDR; extern const unsigned long SIOCGIFADDR;
extern const uint64_t SIOCGIFBR; extern const unsigned long SIOCGIFBR;
extern const uint64_t SIOCGIFBRDADDR; extern const unsigned long SIOCGIFBRDADDR;
extern const uint64_t SIOCGIFCONF; extern const unsigned long SIOCGIFCONF;
extern const uint64_t SIOCGIFCOUNT; extern const unsigned long SIOCGIFCOUNT;
extern const uint64_t SIOCGIFDSTADDR; extern const unsigned long SIOCGIFDSTADDR;
extern const uint64_t SIOCGIFENCAP; extern const unsigned long SIOCGIFENCAP;
extern const uint64_t SIOCGIFFLAGS; extern const unsigned long SIOCGIFFLAGS;
extern const uint64_t SIOCGIFHWADDR; extern const unsigned long SIOCGIFHWADDR;
extern const uint64_t SIOCGIFINDEX; extern const unsigned long SIOCGIFINDEX;
extern const uint64_t SIOCGIFMAP; extern const unsigned long SIOCGIFMAP;
extern const uint64_t SIOCGIFMEM; extern const unsigned long SIOCGIFMEM;
extern const uint64_t SIOCGIFMETRIC; extern const unsigned long SIOCGIFMETRIC;
extern const uint64_t SIOCGIFMTU; extern const unsigned long SIOCGIFMTU;
extern const uint64_t SIOCGIFNAME; extern const unsigned long SIOCGIFNAME;
extern const uint64_t SIOCGIFNETMASK; extern const unsigned long SIOCGIFNETMASK;
extern const uint64_t SIOCGIFPFLAGS; extern const unsigned long SIOCGIFPFLAGS;
extern const uint64_t SIOCGIFSLAVE; extern const unsigned long SIOCGIFSLAVE;
extern const uint64_t SIOCGIFTXQLEN; extern const unsigned long SIOCGIFTXQLEN;
extern const uint64_t SIOCGPGRP; extern const unsigned long SIOCGPGRP;
extern const uint64_t SIOCGRARP; extern const unsigned long SIOCGRARP;
extern const uint64_t SIOCGSTAMP; extern const unsigned long SIOCGSTAMP;
extern const uint64_t SIOCGSTAMPNS; extern const unsigned long SIOCGSTAMPNS;
extern const uint64_t SIOCPROTOPRIVATE; extern const unsigned long SIOCPROTOPRIVATE;
extern const uint64_t SIOCRTMSG; extern const unsigned long SIOCRTMSG;
extern const uint64_t SIOCSARP; extern const unsigned long SIOCSARP;
extern const uint64_t SIOCSIFADDR; extern const unsigned long SIOCSIFADDR;
extern const uint64_t SIOCSIFBR; extern const unsigned long SIOCSIFBR;
extern const uint64_t SIOCSIFBRDADDR; extern const unsigned long SIOCSIFBRDADDR;
extern const uint64_t SIOCSIFDSTADDR; extern const unsigned long SIOCSIFDSTADDR;
extern const uint64_t SIOCSIFENCAP; extern const unsigned long SIOCSIFENCAP;
extern const uint64_t SIOCSIFFLAGS; extern const unsigned long SIOCSIFFLAGS;
extern const uint64_t SIOCSIFHWADDR; extern const unsigned long SIOCSIFHWADDR;
extern const uint64_t SIOCSIFHWBROADCAST; extern const unsigned long SIOCSIFHWBROADCAST;
extern const uint64_t SIOCSIFLINK; extern const unsigned long SIOCSIFLINK;
extern const uint64_t SIOCSIFMAP; extern const unsigned long SIOCSIFMAP;
extern const uint64_t SIOCSIFMEM; extern const unsigned long SIOCSIFMEM;
extern const uint64_t SIOCSIFMETRIC; extern const unsigned long SIOCSIFMETRIC;
extern const uint64_t SIOCSIFMTU; extern const unsigned long SIOCSIFMTU;
extern const uint64_t SIOCSIFNAME; extern const unsigned long SIOCSIFNAME;
extern const uint64_t SIOCSIFNETMASK; extern const unsigned long SIOCSIFNETMASK;
extern const uint64_t SIOCSIFPFLAGS; extern const unsigned long SIOCSIFPFLAGS;
extern const uint64_t SIOCSIFSLAVE; extern const unsigned long SIOCSIFSLAVE;
extern const uint64_t SIOCSIFTXQLEN; extern const unsigned long SIOCSIFTXQLEN;
extern const uint64_t SIOCSPGRP; extern const unsigned long SIOCSPGRP;
extern const uint64_t SIOCSRARP; extern const unsigned long SIOCSRARP;
extern const uint64_t SIOGIFINDEX; extern const unsigned long SIOGIFINDEX;
#define SIOCADDDLCI SIOCADDDLCI #define SIOCGIFCONF SIOCGIFCONF
#define SIOCADDMULTI SIOCADDMULTI #define SIOCGIFADDR SIOCGIFADDR
#define SIOCADDRT SIOCADDRT #define SIOCSIFADDR SIOCSIFADDR
#define SIOCATMARK SIOCATMARK #define SIOCDIFADDR SIOCDIFADDR
#define SIOCDARP SIOCDARP #define SIOCGIFBRDADDR SIOCGIFBRDADDR
#define SIOCDELDLCI SIOCDELDLCI #define SIOCGIFNETMASK SIOCGIFNETMASK
#define SIOCDELMULTI SIOCDELMULTI #define SIOCGIFFLAGS SIOCGIFFLAGS
#define SIOCDELRT SIOCDELRT #define SIOCSIFFLAGS SIOCSIFFLAGS
#define SIOCDEVPRIVATE SIOCDEVPRIVATE #define SIOCGIFMETRIC SIOCGIFMETRIC
#define SIOCDIFADDR SIOCDIFADDR #define SIOCSIFMETRIC SIOCSIFMETRIC
#define SIOCDRARP SIOCDRARP #define SIOCSIFBRDADDR SIOCSIFBRDADDR
#define SIOCGARP SIOCGARP #define SIOCSIFNETMASK SIOCSIFNETMASK
#define SIOCGIFADDR SIOCGIFADDR #define SIOCGIFDSTADDR SIOCGIFDSTADDR
#define SIOCGIFBR SIOCGIFBR #define SIOCSIFDSTADDR SIOCSIFDSTADDR
#define SIOCGIFBRDADDR SIOCGIFBRDADDR #define SIOCGIFMTU SIOCGIFMTU
#define SIOCGIFCONF SIOCGIFCONF #define SIOCSIFMTU SIOCSIFMTU
#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 SIOCGPGRP SIOCGPGRP
#define SIOCSPGRP SIOCSPGRP
#define SIOCADDMULTI SIOCADDMULTI
#define SIOCDELMULTI SIOCDELMULTI
COSMOPOLITAN_C_END_ COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */

View file

@ -155,73 +155,74 @@ extern const uint32_t CRTSCTS;
#define FF1 FF1 #define FF1 FF1
#define FF2 FF2 #define FF2 FF2
#define CLOCAL CLOCAL #define CLOCAL CLOCAL
#define CREAD CREAD #define CREAD CREAD
#define CS5 CS5 #define CS5 CS5
#define CS6 CS6 #define CS6 CS6
#define CS7 CS7 #define CS7 CS7
#define CS8 CS8 #define CS8 CS8
#define CSIZE CSIZE #define CSIZE CSIZE
#define CSTOPB CSTOPB #define CSTOPB CSTOPB
#define ECHO 8 #define ECHO 8
#define ECHOCTL ECHOCTL #define ECHOCTL ECHOCTL
#define ECHOE ECHOE #define ECHOE ECHOE
#define ECHOK ECHOK #define ECHOK ECHOK
#define ECHOKE ECHOKE #define ECHOKE ECHOKE
#define ECHONL ECHONL #define ECHONL ECHONL
#define ECHOPRT ECHOPRT #define ECHOPRT ECHOPRT
#define EXTPROC EXTPROC #define EXTPROC EXTPROC
#define FLUSHO FLUSHO #define FLUSHO FLUSHO
#define HUPCL HUPCL #define HUPCL HUPCL
#define ICANON ICANON #define ICANON ICANON
#define IEXTEN IEXTEN #define IEXTEN IEXTEN
#define ISIG ISIG #define ISIG ISIG
#define IUCLC IUCLC #define IUCLC IUCLC
#define IUTF8 IUTF8 #define IUTF8 IUTF8
#define IXOFF IXOFF #define IXOFF IXOFF
#define IXON IXON #define IXON IXON
#define NOFLSH NOFLSH #define NOFLSH NOFLSH
#define OCRNL OCRNL #define OCRNL OCRNL
#define OFDEL OFDEL #define OFDEL OFDEL
#define OFILL OFILL #define OFILL OFILL
#define OLCUC OLCUC #define OLCUC OLCUC
#define ONLCR ONLCR #define ONLCR ONLCR
#define ONLRET ONLRET #define ONLRET ONLRET
#define ONOCR ONOCR #define ONOCR ONOCR
#define PARENB PARENB #define PARENB PARENB
#define PARODD PARODD #define PARODD PARODD
#define PENDIN PENDIN #define PENDIN PENDIN
#define TIOCCONS TIOCCONS #define TOSTOP TOSTOP
#define TIOCGETD TIOCGETD #define VDISCARD VDISCARD
#define TIOCGWINSZ TIOCGWINSZ #define VEOF VEOF
#define TIOCNOTTY TIOCNOTTY #define VEOL VEOL
#define TIOCNXCL TIOCNXCL #define VEOL2 VEOL2
#define TIOCOUTQ TIOCOUTQ #define VERASE VERASE
#define TIOCSCTTY TIOCSCTTY #define VINTR VINTR
#define TIOCSETD TIOCSETD #define VKILL VKILL
#define TIOCSIG TIOCSIG #define VLNEXT VLNEXT
#define TIOCSPGRP TIOCSPGRP #define VMIN VMIN
#define TIOCSTI TIOCSTI #define VQUIT VQUIT
#define TIOCSWINSZ TIOCSWINSZ #define VREPRINT VREPRINT
#define TOSTOP TOSTOP #define VSTART VSTART
#define VDISCARD VDISCARD #define VSTOP VSTOP
#define VEOF VEOF #define VSUSP VSUSP
#define VEOL VEOL #define VSWTC VSWTC
#define VEOL2 VEOL2 #define VTIME VTIME
#define VERASE VERASE #define VWERASE VWERASE
#define VINTR VINTR #define XCASE XCASE
#define VKILL VKILL
#define VLNEXT VLNEXT /* terminal ioctls */
#define VMIN VMIN #define TIOCGWINSZ TIOCGWINSZ /* get tty dimensions */
#define VQUIT VQUIT #define TIOCSWINSZ TIOCSWINSZ /* set tty dimensions */
#define VREPRINT VREPRINT #define TIOCCONS TIOCCONS /* redirect terminal */
#define VSTART VSTART #define TIOCGETD TIOCGETD /* get line discipline */
#define VSTOP VSTOP #define TIOCSETD TIOCSETD /* set line discipline */
#define VSUSP VSUSP #define TIOCNOTTY TIOCNOTTY /* give up terminal */
#define VSWTC VSWTC #define TIOCNXCL TIOCNXCL /* disable exclusive mode */
#define VTIME VTIME #define TIOCOUTQ TIOCOUTQ /* bytes in output buffer */
#define VWERASE VWERASE #define TIOCSCTTY TIOCSCTTY /* make controlling terminal */
#define XCASE XCASE #define TIOCSIG TIOCSIG /* generate pty signal */
#define TIOCSTI TIOCSTI /* insert fake tty input */
/* tcsetattr() */ /* tcsetattr() */
#define TCSANOW 0 #define TCSANOW 0

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ /*-*- 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 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 Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the 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 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/intrin/bits.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h" #include "libc/intrin/bits.h"
#include "libc/log/check.h" #include "libc/log/check.h"
#include "libc/log/log.h" #include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/mem/gc.internal.h" #include "libc/mem/gc.internal.h"
#include "libc/mem/mem.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/sock/struct/ifconf.h" #include "libc/sock/struct/ifconf.h"
#include "libc/sock/struct/ifreq.h" #include "libc/sock/struct/ifreq.h"
@ -34,7 +33,7 @@
#include "libc/sysv/consts/sock.h" #include "libc/sysv/consts/sock.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
TEST(ioctl_siocgifconf, test) { TEST(siocgifconf, test) {
size_t n; size_t n;
char *data; char *data;
int socketfd; int socketfd;

View file

@ -18,7 +18,6 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/pledge.internal.h" #include "libc/calls/pledge.internal.h"
#include "libc/calls/struct/bpf.internal.h" #include "libc/calls/struct/bpf.internal.h"
#include "libc/calls/struct/filter.internal.h" #include "libc/calls/struct/filter.internal.h"

View file

@ -149,7 +149,7 @@ o/$(MODE)/test/libc/calls/zipread.com.zip.o: private \
-B -B
# TODO(jart): Have pledge() support SIOCGIFCONF # 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 = private .PLEDGE =
o/$(MODE)/test/libc/calls/poll_test.com.runs: \ o/$(MODE)/test/libc/calls/poll_test.com.runs: \

View file

@ -33,7 +33,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include "libc/calls/ioctl.h" #include "libc/calls/calls.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"

View file

@ -129,7 +129,6 @@
#include "third_party/linenoise/linenoise.h" #include "third_party/linenoise/linenoise.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/sig.internal.h" #include "libc/calls/sig.internal.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"

View file

@ -21,7 +21,6 @@
#include "libc/atomic.h" #include "libc/atomic.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/cp.internal.h" #include "libc/calls/cp.internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/makedev.h" #include "libc/calls/makedev.h"
#include "libc/calls/pledge.h" #include "libc/calls/pledge.h"
#include "libc/calls/struct/bpf.internal.h" #include "libc/calls/struct/bpf.internal.h"
@ -100,6 +99,7 @@
#include "libc/sysv/consts/sol.h" #include "libc/sysv/consts/sol.h"
#include "libc/sysv/consts/st.h" #include "libc/sysv/consts/st.h"
#include "libc/sysv/consts/tcp.h" #include "libc/sysv/consts/tcp.h"
#include "libc/sysv/consts/termios.h"
#include "libc/sysv/consts/utime.h" #include "libc/sysv/consts/utime.h"
#include "libc/sysv/consts/w.h" #include "libc/sysv/consts/w.h"
#include "libc/sysv/errfuns.h" #include "libc/sysv/errfuns.h"

View file

@ -6,7 +6,6 @@
*/ */
#define PY_SSIZE_T_CLEAN #define PY_SSIZE_T_CLEAN
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/flock.h" #include "libc/calls/struct/flock.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/sysv/consts/f.h" #include "libc/sysv/consts/f.h"

View file

@ -9,7 +9,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/makedev.h" #include "libc/calls/makedev.h"
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"

View file

@ -6,7 +6,6 @@
*/ */
#include "third_party/python/Modules/socketmodule.h" #include "third_party/python/Modules/socketmodule.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/weirdtypes.h" #include "libc/calls/weirdtypes.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/dns/dns.h" #include "libc/dns/dns.h"

View file

@ -4,21 +4,20 @@
Python 3 Python 3
https://docs.python.org/3/license.html │ https://docs.python.org/3/license.html │
*/ */
#include "third_party/python/Include/fileutils.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
#include "libc/str/locale.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#include "libc/str/unicode.h"
#include "libc/sysv/consts/f.h" #include "libc/sysv/consts/f.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/fio.h"
#include "libc/sysv/consts/o.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/bytesobject.h"
#include "third_party/python/Include/ceval.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/object.h"
#include "third_party/python/Include/osdefs.h" #include "third_party/python/Include/osdefs.h"
#include "third_party/python/Include/pyerrors.h" #include "third_party/python/Include/pyerrors.h"

View file

@ -26,7 +26,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"

View file

@ -32,7 +32,6 @@
* SUCH DAMAGE. * SUCH DAMAGE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/errno.h" #include "libc/errno.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"

View file

@ -117,7 +117,6 @@
#endif #endif
#if SQLITE_ENABLE_LOCKING_STYLE #if SQLITE_ENABLE_LOCKING_STYLE
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/fio.h"

View file

@ -33,7 +33,6 @@
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "third_party/unzip/crypt.h" #include "third_party/unzip/crypt.h"
#include "libc/sysv/consts/termios.h" #include "libc/sysv/consts/termios.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "third_party/unzip/globals.h" #include "third_party/unzip/globals.h"

View file

@ -110,7 +110,6 @@
#if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE)) #if (defined(UNZIP) && !defined(FUNZIP) && defined(UNIX) && defined(MORE))
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/fio.h"
@ -160,7 +159,6 @@
# ifndef CMS_MVS # ifndef CMS_MVS
# if (!defined(MINIX) && !defined(GOT_IOCTL_H)) # if (!defined(MINIX) && !defined(GOT_IOCTL_H))
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/sysv/consts/fd.h" #include "libc/sysv/consts/fd.h"
#include "libc/sysv/consts/fio.h" #include "libc/sysv/consts/fio.h"

View file

@ -18,7 +18,6 @@
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/copyfile.h" #include "libc/calls/copyfile.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/itimerval.h" #include "libc/calls/struct/itimerval.h"
#include "libc/calls/struct/rlimit.h" #include "libc/calls/struct/rlimit.h"
#include "libc/calls/struct/rusage.h" #include "libc/calls/struct/rusage.h"

View file

@ -13,8 +13,8 @@
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUTPATH OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/errno.h" #include "libc/errno.h"
@ -57,9 +57,48 @@ PERFORMANCE OF THIS SOFTWARE. │
"copyright 2023 justine tunney\n" \ "copyright 2023 justine tunney\n" \
"https://github.com/jart/cosmopolitan\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 { struct Source {
unsigned hash; unsigned hash;
@ -87,6 +126,8 @@ struct Edges {
struct Edge *p; struct Edge *p;
}; };
static const char kSourceExts[][5] = {".s", ".S", ".c", ".cc", ".cpp"};
static char *names; static char *names;
static unsigned counter; static unsigned counter;
static const char *prog; static const char *prog;
@ -295,24 +336,7 @@ static void LoadRelationships(int argc, char *argv[]) {
} }
static wontreturn void ShowUsage(int rc, int fd) { static wontreturn void ShowUsage(int rc, int fd) {
tinyprint(fd, VERSION, tinyprint(fd, VERSION, "\nUSAGE\n\n ", prog, MANUAL, NULL);
"\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);
exit(rc); exit(rc);
} }

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"

View file

@ -20,7 +20,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/atomic.h" #include "libc/atomic.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/pledge.h" #include "libc/calls/pledge.h"
#include "libc/calls/struct/dirent.h" #include "libc/calls/struct/dirent.h"
#include "libc/calls/struct/flock.h" #include "libc/calls/struct/flock.h"

View file

@ -18,7 +18,6 @@
*/ */
#include "dsp/scale/scale.h" #include "dsp/scale/scale.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"

View file

@ -19,7 +19,6 @@
#include "dsp/tty/itoa8.h" #include "dsp/tty/itoa8.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "dsp/scale/cdecimate2xuint8x8.h" #include "dsp/scale/cdecimate2xuint8x8.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"
#include "libc/fmt/conv.h" #include "libc/fmt/conv.h"

View file

@ -18,7 +18,6 @@
*/ */
#include "dsp/scale/scale.h" #include "dsp/scale/scale.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/termios.h" #include "libc/calls/struct/termios.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"

View file

@ -18,7 +18,6 @@
*/ */
#include "dsp/scale/cdecimate2xuint8x8.h" #include "dsp/scale/cdecimate2xuint8x8.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo.h" #include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"

View file

@ -23,7 +23,6 @@
#include "dsp/tty/tty.h" #include "dsp/tty/tty.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"

View file

@ -22,7 +22,6 @@
#include "dsp/tty/quant.h" #include "dsp/tty/quant.h"
#include "dsp/tty/tty.h" #include "dsp/tty/tty.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/stat.h" #include "libc/calls/struct/stat.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/termios.h" #include "libc/calls/termios.h"

View file

@ -26,7 +26,6 @@
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/calls/ioctl.h"
#include "libc/calls/struct/framebufferfixedscreeninfo.h" #include "libc/calls/struct/framebufferfixedscreeninfo.h"
#include "libc/calls/struct/framebuffervirtualscreeninfo.h" #include "libc/calls/struct/framebuffervirtualscreeninfo.h"
#include "libc/calls/struct/iovec.h" #include "libc/calls/struct/iovec.h"