mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
1002 lines
24 KiB
C
1002 lines
24 KiB
C
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
|
│ │
|
|
│ Permission to use, copy, modify, and/or distribute this software for │
|
|
│ any purpose with or without fee is hereby granted, provided that the │
|
|
│ above copyright notice and this permission notice appear in all copies. │
|
|
│ │
|
|
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
|
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
|
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
|
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
|
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
|
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
|
#include "libc/errno.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/af.h"
|
|
#include "libc/sysv/consts/at.h"
|
|
#include "libc/sysv/consts/clock.h"
|
|
#include "libc/sysv/consts/f.h"
|
|
#include "libc/sysv/consts/fd.h"
|
|
#include "libc/sysv/consts/ip.h"
|
|
#include "libc/sysv/consts/ipproto.h"
|
|
#include "libc/sysv/consts/lock.h"
|
|
#include "libc/sysv/consts/madv.h"
|
|
#include "libc/sysv/consts/map.h"
|
|
#include "libc/sysv/consts/msync.h"
|
|
#include "libc/sysv/consts/o.h"
|
|
#include "libc/sysv/consts/ok.h"
|
|
#include "libc/sysv/consts/rusage.h"
|
|
#include "libc/sysv/consts/sicode.h"
|
|
#include "libc/sysv/consts/sig.h"
|
|
#include "libc/sysv/consts/so.h"
|
|
#include "libc/sysv/consts/sock.h"
|
|
#include "libc/sysv/consts/sol.h"
|
|
#include "libc/sysv/consts/tcp.h"
|
|
#include "libc/sysv/consts/termios.h"
|
|
#include "libc/sysv/consts/w.h"
|
|
#include "libc/sysv/errfuns.h"
|
|
#include "tool/build/lib/case.h"
|
|
#include "tool/build/lib/endian.h"
|
|
#include "tool/build/lib/xlat.h"
|
|
|
|
#define XLAT(x, y) CASE(x, return y)
|
|
|
|
int XlatSignal(int x) {
|
|
switch (x) {
|
|
XLAT(1, SIGHUP);
|
|
XLAT(2, SIGINT);
|
|
XLAT(3, SIGQUIT);
|
|
XLAT(4, SIGILL);
|
|
XLAT(5, SIGTRAP);
|
|
XLAT(6, SIGABRT);
|
|
XLAT(7, SIGBUS);
|
|
XLAT(8, SIGFPE);
|
|
XLAT(9, SIGKILL);
|
|
XLAT(10, SIGUSR1);
|
|
XLAT(11, SIGSEGV);
|
|
XLAT(12, SIGUSR2);
|
|
XLAT(13, SIGPIPE);
|
|
XLAT(14, SIGALRM);
|
|
XLAT(15, SIGTERM);
|
|
XLAT(17, SIGCHLD);
|
|
XLAT(18, SIGCONT);
|
|
XLAT(21, SIGTTIN);
|
|
XLAT(22, SIGTTOU);
|
|
XLAT(24, SIGXCPU);
|
|
XLAT(25, SIGXFSZ);
|
|
XLAT(26, SIGVTALRM);
|
|
XLAT(27, SIGPROF);
|
|
XLAT(28, SIGWINCH);
|
|
XLAT(29, SIGIO);
|
|
XLAT(19, SIGSTOP);
|
|
XLAT(31, SIGSYS);
|
|
XLAT(20, SIGTSTP);
|
|
XLAT(23, SIGURG);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int UnXlatSignal(int x) {
|
|
if (x == SIGHUP) return 1;
|
|
if (x == SIGINT) return 2;
|
|
if (x == SIGQUIT) return 3;
|
|
if (x == SIGILL) return 4;
|
|
if (x == SIGTRAP) return 5;
|
|
if (x == SIGABRT) return 6;
|
|
if (x == SIGBUS) return 7;
|
|
if (x == SIGFPE) return 8;
|
|
if (x == SIGKILL) return 9;
|
|
if (x == SIGUSR1) return 10;
|
|
if (x == SIGSEGV) return 11;
|
|
if (x == SIGUSR2) return 12;
|
|
if (x == SIGPIPE) return 13;
|
|
if (x == SIGALRM) return 14;
|
|
if (x == SIGTERM) return 15;
|
|
if (x == SIGCHLD) return 17;
|
|
if (x == SIGCONT) return 18;
|
|
if (x == SIGTTIN) return 21;
|
|
if (x == SIGTTOU) return 22;
|
|
if (x == SIGXCPU) return 24;
|
|
if (x == SIGXFSZ) return 25;
|
|
if (x == SIGVTALRM) return 26;
|
|
if (x == SIGPROF) return 27;
|
|
if (x == SIGWINCH) return 28;
|
|
if (x == SIGIO) return 29;
|
|
if (x == SIGSTOP) return 19;
|
|
if (x == SIGSYS) return 31;
|
|
if (x == SIGTSTP) return 20;
|
|
if (x == SIGURG) return 23;
|
|
return 15;
|
|
}
|
|
|
|
int UnXlatSicode(int sig, int code) {
|
|
if (code == SI_USER) return 0;
|
|
if (code == SI_QUEUE) return -1;
|
|
if (code == SI_TIMER) return -2;
|
|
if (code == SI_TKILL) return -6;
|
|
if (code == SI_MESGQ) return -3;
|
|
if (code == SI_ASYNCIO) return -4;
|
|
if (code == SI_ASYNCNL) return -60;
|
|
if (code == SI_KERNEL) return 0x80;
|
|
if (sig == SIGCHLD) {
|
|
if (code == CLD_EXITED) return 1;
|
|
if (code == CLD_KILLED) return 2;
|
|
if (code == CLD_DUMPED) return 3;
|
|
if (code == CLD_TRAPPED) return 4;
|
|
if (code == CLD_STOPPED) return 5;
|
|
if (code == CLD_CONTINUED) return 6;
|
|
return -1;
|
|
}
|
|
if (sig == SIGTRAP) {
|
|
if (code == TRAP_BRKPT) return 1;
|
|
if (code == TRAP_TRACE) return 2;
|
|
return -1;
|
|
}
|
|
if (sig == SIGSEGV) {
|
|
if (code == SEGV_MAPERR) return 1;
|
|
if (code == SEGV_ACCERR) return 2;
|
|
return -1;
|
|
}
|
|
if (sig == SIGFPE) {
|
|
if (code == FPE_INTDIV) return 1;
|
|
if (code == FPE_INTOVF) return 2;
|
|
if (code == FPE_FLTDIV) return 3;
|
|
if (code == FPE_FLTOVF) return 4;
|
|
if (code == FPE_FLTUND) return 5;
|
|
if (code == FPE_FLTRES) return 6;
|
|
if (code == FPE_FLTINV) return 7;
|
|
if (code == FPE_FLTSUB) return 8;
|
|
return -1;
|
|
}
|
|
if (sig == SIGILL) {
|
|
if (code == ILL_ILLOPC) return 1;
|
|
if (code == ILL_ILLOPN) return 2;
|
|
if (code == ILL_ILLADR) return 3;
|
|
if (code == ILL_ILLTRP) return 4;
|
|
if (code == ILL_PRVOPC) return 5;
|
|
if (code == ILL_PRVREG) return 6;
|
|
if (code == ILL_COPROC) return 7;
|
|
if (code == ILL_BADSTK) return 8;
|
|
return -1;
|
|
}
|
|
if (sig == SIGBUS) {
|
|
if (code == BUS_ADRALN) return 1;
|
|
if (code == BUS_ADRERR) return 2;
|
|
if (code == BUS_OBJERR) return 3;
|
|
if (code == BUS_MCEERR_AR) return 4;
|
|
if (code == BUS_MCEERR_AO) return 5;
|
|
return -1;
|
|
}
|
|
if (sig == SIGIO) {
|
|
if (code == POLL_IN) return 1;
|
|
if (code == POLL_OUT) return 2;
|
|
if (code == POLL_MSG) return 3;
|
|
if (code == POLL_ERR) return 4;
|
|
if (code == POLL_PRI) return 5;
|
|
if (code == POLL_HUP) return 6;
|
|
return -1;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int XlatSig(int x) {
|
|
switch (x) {
|
|
XLAT(0, SIG_BLOCK);
|
|
XLAT(1, SIG_UNBLOCK);
|
|
XLAT(2, SIG_SETMASK);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatRusage(int x) {
|
|
switch (x) {
|
|
XLAT(0, RUSAGE_SELF);
|
|
XLAT(-1, RUSAGE_CHILDREN);
|
|
XLAT(1, RUSAGE_THREAD);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatSocketFamily(int x) {
|
|
switch (x) {
|
|
XLAT(0, AF_UNSPEC);
|
|
XLAT(1, AF_UNIX);
|
|
XLAT(2, AF_INET);
|
|
default:
|
|
errno = EPFNOSUPPORT;
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
int UnXlatSocketFamily(int x) {
|
|
switch (x) {
|
|
XLAT(AF_UNSPEC, 0);
|
|
XLAT(AF_UNIX, 1);
|
|
XLAT(AF_INET, 2);
|
|
default:
|
|
return x;
|
|
}
|
|
}
|
|
|
|
int XlatSocketType(int x) {
|
|
switch (x) {
|
|
XLAT(1, SOCK_STREAM);
|
|
XLAT(2, SOCK_DGRAM);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatSocketFlags(int flags) {
|
|
unsigned res = 0;
|
|
if (flags & 0x080000) res |= SOCK_CLOEXEC;
|
|
if (flags & 0x000800) res |= SOCK_NONBLOCK;
|
|
return res;
|
|
}
|
|
|
|
int XlatSocketProtocol(int x) {
|
|
switch (x) {
|
|
XLAT(0, 0);
|
|
XLAT(6, IPPROTO_TCP);
|
|
XLAT(17, IPPROTO_UDP);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatSocketLevel(int level) {
|
|
switch (level) {
|
|
XLAT(0, SOL_IP);
|
|
XLAT(1, SOL_SOCKET);
|
|
XLAT(6, SOL_TCP);
|
|
XLAT(17, SOL_UDP);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatSocketOptname(int level, int optname) {
|
|
if (level == SOL_SOCKET) {
|
|
switch (optname) {
|
|
XLAT(1, SO_DEBUG);
|
|
XLAT(2, SO_REUSEADDR);
|
|
XLAT(3, SO_TYPE);
|
|
XLAT(4, SO_ERROR);
|
|
XLAT(5, SO_DONTROUTE);
|
|
XLAT(6, SO_BROADCAST);
|
|
XLAT(7, SO_SNDBUF);
|
|
XLAT(8, SO_RCVBUF);
|
|
XLAT(9, SO_KEEPALIVE);
|
|
XLAT(13, SO_LINGER);
|
|
XLAT(15, SO_REUSEPORT);
|
|
XLAT(18, SO_RCVLOWAT);
|
|
XLAT(19, SO_SNDLOWAT);
|
|
XLAT(30, SO_ACCEPTCONN);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
if (level == SOL_TCP) {
|
|
switch (optname) {
|
|
XLAT(1, TCP_NODELAY);
|
|
XLAT(2, TCP_MAXSEG);
|
|
#if defined(TCP_CORK)
|
|
XLAT(3, TCP_CORK);
|
|
#elif defined(TCP_NOPUSH)
|
|
XLAT(3, TCP_NOPUSH);
|
|
#endif
|
|
#ifdef TCP_KEEPIDLE
|
|
XLAT(4, TCP_KEEPIDLE);
|
|
#endif
|
|
#ifdef TCP_KEEPINTVL
|
|
XLAT(5, TCP_KEEPINTVL);
|
|
#endif
|
|
#ifdef TCP_KEEPCNT
|
|
XLAT(6, TCP_KEEPCNT);
|
|
#endif
|
|
#ifdef TCP_SYNCNT
|
|
XLAT(7, TCP_SYNCNT);
|
|
#endif
|
|
#ifdef TCP_WINDOW_CLAMP
|
|
XLAT(10, TCP_WINDOW_CLAMP);
|
|
#endif
|
|
#ifdef TCP_FASTOPEN
|
|
XLAT(23, TCP_FASTOPEN);
|
|
#endif
|
|
#ifdef TCP_QUICKACK
|
|
XLAT(12, TCP_QUICKACK);
|
|
#endif
|
|
#ifdef TCP_NOTSENT_LOWAT
|
|
XLAT(25, TCP_NOTSENT_LOWAT);
|
|
#endif
|
|
#ifdef TCP_SAVE_SYN
|
|
XLAT(27, TCP_SAVE_SYN);
|
|
#endif
|
|
#ifdef TCP_FASTOPEN_CONNECT
|
|
XLAT(30, TCP_FASTOPEN_CONNECT);
|
|
#endif
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
if (level == SOL_IP) {
|
|
switch (optname) {
|
|
XLAT(1, IP_TOS);
|
|
XLAT(2, IP_TTL);
|
|
XLAT(3, IP_HDRINCL);
|
|
XLAT(14, IP_MTU);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
return einval();
|
|
}
|
|
|
|
int XlatAccess(int x) {
|
|
int r = F_OK;
|
|
if (x & 1) r |= X_OK;
|
|
if (x & 2) r |= W_OK;
|
|
if (x & 4) r |= R_OK;
|
|
return r;
|
|
}
|
|
|
|
int XlatLock(int x) {
|
|
int r = 0;
|
|
if (x & 1) r |= LOCK_SH;
|
|
if (x & 2) r |= LOCK_EX;
|
|
if (x & 4) r |= LOCK_NB;
|
|
if (x & 8) r |= LOCK_UN;
|
|
return r;
|
|
}
|
|
|
|
int XlatWait(int x) {
|
|
int r = 0;
|
|
if (x & 1) r |= WNOHANG;
|
|
if (x & 2) r |= WUNTRACED;
|
|
if (x & 8) r |= WCONTINUED;
|
|
return r;
|
|
}
|
|
|
|
int XlatMapFlags(int x) {
|
|
int r = 0;
|
|
if (x & 1) r |= MAP_SHARED;
|
|
if (x & 2) r |= MAP_PRIVATE;
|
|
if (x & 16) r |= MAP_FIXED;
|
|
if (x & 32) r |= MAP_ANONYMOUS;
|
|
return r;
|
|
}
|
|
|
|
int XlatMsyncFlags(int x) {
|
|
unsigned res = 0;
|
|
if (x & 1) res |= MS_ASYNC;
|
|
if (x & 2) res |= MS_INVALIDATE;
|
|
if (x & 4) res |= MS_SYNC;
|
|
return res;
|
|
}
|
|
|
|
int XlatClock(int x) {
|
|
switch (x) {
|
|
XLAT(0, CLOCK_REALTIME);
|
|
XLAT(1, CLOCK_MONOTONIC);
|
|
XLAT(2, CLOCK_PROCESS_CPUTIME_ID);
|
|
#ifdef CLOCK_MONOTONIC_RAW
|
|
XLAT(4, CLOCK_MONOTONIC_RAW);
|
|
#endif
|
|
default:
|
|
return x;
|
|
}
|
|
}
|
|
|
|
int XlatAtf(int x) {
|
|
int res = 0;
|
|
if (x & 0x0100) res |= AT_SYMLINK_NOFOLLOW;
|
|
if (x & 0x0200) res |= AT_REMOVEDIR;
|
|
if (x & 0x0400) res |= AT_SYMLINK_FOLLOW;
|
|
if (x & 0x1000) res |= AT_EMPTY_PATH;
|
|
return res;
|
|
}
|
|
|
|
int XlatOpenMode(int flags) {
|
|
switch (flags & 3) {
|
|
case 0:
|
|
return O_RDONLY;
|
|
case 1:
|
|
return O_WRONLY;
|
|
case 2:
|
|
return O_RDWR;
|
|
default:
|
|
for (;;) (void)0;
|
|
}
|
|
}
|
|
|
|
int XlatOpenFlags(int flags) {
|
|
int res;
|
|
res = XlatOpenMode(flags);
|
|
if (flags & 0x00400) res |= O_APPEND;
|
|
if (flags & 0x00040) res |= O_CREAT;
|
|
if (flags & 0x00080) res |= O_EXCL;
|
|
if (flags & 0x00200) res |= O_TRUNC;
|
|
if (flags & 0x00800) res |= O_NDELAY;
|
|
if (flags & 0x04000) res |= O_DIRECT;
|
|
if (flags & 0x10000) res |= O_DIRECTORY;
|
|
if (flags & 0x20000) res |= O_NOFOLLOW;
|
|
if (flags & 0x80000) res |= O_CLOEXEC;
|
|
if (flags & 0x00100) res |= O_NOCTTY;
|
|
#ifdef O_ASYNC
|
|
if (flags & 0x02000) res |= O_ASYNC;
|
|
#endif
|
|
#ifdef O_NOATIME
|
|
if (flags & 0x40000) res |= O_NOATIME;
|
|
#endif
|
|
#ifdef O_DSYNC
|
|
if (flags & 0x000001000) res |= O_DSYNC;
|
|
#endif
|
|
#ifdef O_SYNC
|
|
if ((flags & 0x00101000) == 0x00101000) res |= O_SYNC;
|
|
#endif
|
|
return res;
|
|
}
|
|
|
|
int XlatFcntlCmd(int x) {
|
|
switch (x) {
|
|
XLAT(1, F_GETFD);
|
|
XLAT(2, F_SETFD);
|
|
XLAT(3, F_GETFL);
|
|
XLAT(4, F_SETFL);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatFcntlArg(int x) {
|
|
switch (x) {
|
|
XLAT(0, 0);
|
|
XLAT(1, FD_CLOEXEC);
|
|
XLAT(0x0800, O_NONBLOCK);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
int XlatAdvice(int x) {
|
|
switch (x) {
|
|
XLAT(0, MADV_NORMAL);
|
|
XLAT(1, MADV_RANDOM);
|
|
XLAT(2, MADV_SEQUENTIAL);
|
|
XLAT(3, MADV_WILLNEED);
|
|
XLAT(4, MADV_DONTNEED);
|
|
XLAT(8, MADV_FREE);
|
|
XLAT(12, MADV_MERGEABLE);
|
|
default:
|
|
return einval();
|
|
}
|
|
}
|
|
|
|
void XlatSockaddrToHost(struct sockaddr_in *dst,
|
|
const struct sockaddr_in_bits *src) {
|
|
memset(dst, 0, sizeof(*dst));
|
|
dst->sin_family = XlatSocketFamily(Read16(src->sin_family));
|
|
dst->sin_port = src->sin_port;
|
|
dst->sin_addr.s_addr = src->sin_addr;
|
|
}
|
|
|
|
void XlatSockaddrToLinux(struct sockaddr_in_bits *dst,
|
|
const struct sockaddr_in *src) {
|
|
memset(dst, 0, sizeof(*dst));
|
|
Write16(dst->sin_family, UnXlatSocketFamily(src->sin_family));
|
|
dst->sin_port = src->sin_port;
|
|
dst->sin_addr = src->sin_addr.s_addr;
|
|
}
|
|
|
|
void XlatStatToLinux(struct stat_bits *dst, const struct stat *src) {
|
|
Write64(dst->st_dev, src->st_dev);
|
|
Write64(dst->st_ino, src->st_ino);
|
|
Write64(dst->st_nlink, src->st_nlink);
|
|
Write32(dst->st_mode, src->st_mode);
|
|
Write32(dst->st_uid, src->st_uid);
|
|
Write32(dst->st_gid, src->st_gid);
|
|
Write32(dst->__pad, 0);
|
|
Write64(dst->st_rdev, src->st_rdev);
|
|
Write64(dst->st_size, src->st_size);
|
|
Write64(dst->st_blksize, src->st_blksize);
|
|
Write64(dst->st_blocks, src->st_blocks);
|
|
Write64(dst->st_dev, src->st_dev);
|
|
Write64(dst->st_atim.tv_sec, src->st_atim.tv_sec);
|
|
Write64(dst->st_atim.tv_nsec, src->st_atim.tv_nsec);
|
|
Write64(dst->st_mtim.tv_sec, src->st_mtim.tv_sec);
|
|
Write64(dst->st_mtim.tv_nsec, src->st_mtim.tv_nsec);
|
|
Write64(dst->st_ctim.tv_sec, src->st_ctim.tv_sec);
|
|
Write64(dst->st_ctim.tv_nsec, src->st_ctim.tv_nsec);
|
|
}
|
|
|
|
void XlatRusageToLinux(struct rusage_bits *dst, const struct rusage *src) {
|
|
Write64(dst->ru_utime.tv_sec, src->ru_utime.tv_sec);
|
|
Write64(dst->ru_utime.tv_usec, src->ru_utime.tv_usec);
|
|
Write64(dst->ru_stime.tv_sec, src->ru_stime.tv_sec);
|
|
Write64(dst->ru_stime.tv_usec, src->ru_stime.tv_usec);
|
|
Write64(dst->ru_maxrss, src->ru_maxrss);
|
|
Write64(dst->ru_ixrss, src->ru_ixrss);
|
|
Write64(dst->ru_idrss, src->ru_idrss);
|
|
Write64(dst->ru_isrss, src->ru_isrss);
|
|
Write64(dst->ru_minflt, src->ru_minflt);
|
|
Write64(dst->ru_majflt, src->ru_majflt);
|
|
Write64(dst->ru_nswap, src->ru_nswap);
|
|
Write64(dst->ru_inblock, src->ru_inblock);
|
|
Write64(dst->ru_oublock, src->ru_oublock);
|
|
Write64(dst->ru_msgsnd, src->ru_msgsnd);
|
|
Write64(dst->ru_msgrcv, src->ru_msgrcv);
|
|
Write64(dst->ru_nsignals, src->ru_nsignals);
|
|
Write64(dst->ru_nvcsw, src->ru_nvcsw);
|
|
Write64(dst->ru_nivcsw, src->ru_nivcsw);
|
|
}
|
|
|
|
void XlatItimervalToLinux(struct itimerval_bits *dst,
|
|
const struct itimerval *src) {
|
|
Write64(dst->it_interval.tv_sec, src->it_interval.tv_sec);
|
|
Write64(dst->it_interval.tv_usec, src->it_interval.tv_usec);
|
|
Write64(dst->it_value.tv_sec, src->it_value.tv_sec);
|
|
Write64(dst->it_value.tv_usec, src->it_value.tv_usec);
|
|
}
|
|
|
|
void XlatLinuxToItimerval(struct itimerval *dst,
|
|
const struct itimerval_bits *src) {
|
|
dst->it_interval.tv_sec = Read64(src->it_interval.tv_sec);
|
|
dst->it_interval.tv_usec = Read64(src->it_interval.tv_usec);
|
|
dst->it_value.tv_sec = Read64(src->it_value.tv_sec);
|
|
dst->it_value.tv_usec = Read64(src->it_value.tv_usec);
|
|
}
|
|
|
|
void XlatWinsizeToLinux(struct winsize_bits *dst, const struct winsize *src) {
|
|
memset(dst, 0, sizeof(*dst));
|
|
Write16(dst->ws_row, src->ws_row);
|
|
Write16(dst->ws_col, src->ws_col);
|
|
}
|
|
|
|
void XlatSigsetToLinux(uint8_t dst[8], const sigset_t *src) {
|
|
int i;
|
|
uint64_t x;
|
|
for (x = i = 0; i < 64; ++i) {
|
|
if (sigismember(src, i + 1)) {
|
|
x |= 1ull << i;
|
|
}
|
|
}
|
|
Write64(dst, x);
|
|
}
|
|
|
|
void XlatLinuxToSigset(sigset_t *dst, const uint8_t src[8]) {
|
|
int i;
|
|
uint64_t x;
|
|
x = Read64(src);
|
|
sigemptyset(dst);
|
|
for (i = 0; i < 64; ++i) {
|
|
if ((1ull << i) & x) {
|
|
sigaddset(dst, i + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int XlatTermiosCflag(int x) {
|
|
int r = 0;
|
|
if (x & 0x0001) r |= ISIG;
|
|
if (x & 0x0040) r |= CSTOPB;
|
|
if (x & 0x0080) r |= CREAD;
|
|
if (x & 0x0100) r |= PARENB;
|
|
if (x & 0x0200) r |= PARODD;
|
|
if (x & 0x0400) r |= HUPCL;
|
|
if (x & 0x0800) r |= CLOCAL;
|
|
if ((x & 0x0030) == 0x0010) {
|
|
r |= CS6;
|
|
} else if ((x & 0x0030) == 0x0020) {
|
|
r |= CS7;
|
|
} else if ((x & 0x0030) == 0x0030) {
|
|
r |= CS8;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
static int UnXlatTermiosCflag(int x) {
|
|
int r = 0;
|
|
if (x & ISIG) r |= 0x0001;
|
|
if (x & CSTOPB) r |= 0x0040;
|
|
if (x & CREAD) r |= 0x0080;
|
|
if (x & PARENB) r |= 0x0100;
|
|
if (x & PARODD) r |= 0x0200;
|
|
if (x & HUPCL) r |= 0x0400;
|
|
if (x & CLOCAL) r |= 0x0800;
|
|
if ((x & CSIZE) == CS5) {
|
|
r |= 0x0000;
|
|
} else if ((x & CSIZE) == CS6) {
|
|
r |= 0x0010;
|
|
} else if ((x & CSIZE) == CS7) {
|
|
r |= 0x0020;
|
|
} else if ((x & CSIZE) == CS8) {
|
|
r |= 0x0030;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
static int XlatTermiosLflag(int x) {
|
|
int r = 0;
|
|
if (x & 0x0001) r |= ISIG;
|
|
if (x & 0x0002) r |= ICANON;
|
|
if (x & 0x0008) r |= ECHO;
|
|
if (x & 0x0010) r |= ECHOE;
|
|
if (x & 0x0020) r |= ECHOK;
|
|
if (x & 0x0040) r |= ECHONL;
|
|
if (x & 0x0080) r |= NOFLSH;
|
|
if (x & 0x0100) r |= TOSTOP;
|
|
if (x & 0x8000) r |= IEXTEN;
|
|
#ifdef ECHOCTL
|
|
if (x & 0x0200) r |= ECHOCTL;
|
|
#endif
|
|
#ifdef ECHOPRT
|
|
if (x & 0x0400) r |= ECHOPRT;
|
|
#endif
|
|
#ifdef ECHOKE
|
|
if (x & 0x0800) r |= ECHOKE;
|
|
#endif
|
|
#ifdef FLUSHO
|
|
if (x & 0x1000) r |= FLUSHO;
|
|
#endif
|
|
#ifdef PENDIN
|
|
if (x & 0x4000) r |= PENDIN;
|
|
#endif
|
|
#ifdef XCASE
|
|
if (x & 0x0004) r |= XCASE;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static int UnXlatTermiosLflag(int x) {
|
|
int r = 0;
|
|
if (x & ISIG) r |= 0x0001;
|
|
if (x & ICANON) r |= 0x0002;
|
|
if (x & ECHO) r |= 0x0008;
|
|
if (x & ECHOE) r |= 0x0010;
|
|
if (x & ECHOK) r |= 0x0020;
|
|
if (x & ECHONL) r |= 0x0040;
|
|
if (x & NOFLSH) r |= 0x0080;
|
|
if (x & TOSTOP) r |= 0x0100;
|
|
if (x & IEXTEN) r |= 0x8000;
|
|
#ifdef ECHOCTL
|
|
if (x & ECHOCTL) r |= 0x0200;
|
|
#endif
|
|
#ifdef ECHOPRT
|
|
if (x & ECHOPRT) r |= 0x0400;
|
|
#endif
|
|
#ifdef ECHOKE
|
|
if (x & ECHOKE) r |= 0x0800;
|
|
#endif
|
|
#ifdef FLUSHO
|
|
if (x & FLUSHO) r |= 0x1000;
|
|
#endif
|
|
#ifdef PENDIN
|
|
if (x & PENDIN) r |= 0x4000;
|
|
#endif
|
|
#ifdef XCASE
|
|
if (x & XCASE) r |= 0x0004;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static int XlatTermiosIflag(int x) {
|
|
int r = 0;
|
|
if (x & 0x0001) r |= IGNBRK;
|
|
if (x & 0x0002) r |= BRKINT;
|
|
if (x & 0x0004) r |= IGNPAR;
|
|
if (x & 0x0008) r |= PARMRK;
|
|
if (x & 0x0010) r |= INPCK;
|
|
if (x & 0x0020) r |= ISTRIP;
|
|
if (x & 0x0040) r |= INLCR;
|
|
if (x & 0x0080) r |= IGNCR;
|
|
if (x & 0x0100) r |= ICRNL;
|
|
if (x & 0x0400) r |= IXON;
|
|
if (x & 0x0800) r |= IXANY;
|
|
if (x & 0x1000) r |= IXOFF;
|
|
#ifdef IMAXBEL
|
|
if (x & 0x2000) r |= IMAXBEL;
|
|
#endif
|
|
#ifdef IUTF8
|
|
if (x & 0x4000) r |= IUTF8;
|
|
#endif
|
|
#ifdef IUCLC
|
|
if (x & 0x0200) r |= IUCLC;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static int UnXlatTermiosIflag(int x) {
|
|
int r = 0;
|
|
if (x & IGNBRK) r |= 0x0001;
|
|
if (x & BRKINT) r |= 0x0002;
|
|
if (x & IGNPAR) r |= 0x0004;
|
|
if (x & PARMRK) r |= 0x0008;
|
|
if (x & INPCK) r |= 0x0010;
|
|
if (x & ISTRIP) r |= 0x0020;
|
|
if (x & INLCR) r |= 0x0040;
|
|
if (x & IGNCR) r |= 0x0080;
|
|
if (x & ICRNL) r |= 0x0100;
|
|
if (x & IXON) r |= 0x0400;
|
|
if (x & IXANY) r |= 0x0800;
|
|
if (x & IXOFF) r |= 0x1000;
|
|
#ifdef IMAXBEL
|
|
if (x & IMAXBEL) r |= 0x2000;
|
|
#endif
|
|
#ifdef IUTF8
|
|
if (x & IUTF8) r |= 0x4000;
|
|
#endif
|
|
#ifdef IUCLC
|
|
if (x & IUCLC) r |= 0x0200;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static int XlatTermiosOflag(int x) {
|
|
int r = 0;
|
|
if (x & 0x0001) r |= OPOST;
|
|
#ifdef ONLCR
|
|
if (x & 0x0004) r |= ONLCR;
|
|
#endif
|
|
#ifdef OCRNL
|
|
if (x & 0x0008) r |= OCRNL;
|
|
#endif
|
|
#ifdef ONOCR
|
|
if (x & 0x0010) r |= ONOCR;
|
|
#endif
|
|
#ifdef ONLRET
|
|
if (x & 0x0020) r |= ONLRET;
|
|
#endif
|
|
#ifdef OFILL
|
|
if (x & 0x0040) r |= OFILL;
|
|
#endif
|
|
#ifdef OFDEL
|
|
if (x & 0x0080) r |= OFDEL;
|
|
#endif
|
|
#ifdef NLDLY
|
|
if ((x & 0x0100) == 0x0000) {
|
|
r |= NL0;
|
|
} else if ((x & 0x0100) == 0x0100) {
|
|
r |= NL1;
|
|
#ifdef NL2
|
|
} else if ((x & 0x0100) == 0x0000) {
|
|
r |= NL2;
|
|
#endif
|
|
#ifdef NL3
|
|
} else if ((x & 0x0100) == 0x0000) {
|
|
r |= NL3;
|
|
#endif
|
|
}
|
|
#endif
|
|
#ifdef CRDLY
|
|
if ((x & 0x0600) == 0x0000) {
|
|
r |= CR0;
|
|
} else if ((x & 0x0600) == 0x0200) {
|
|
r |= CR1;
|
|
} else if ((x & 0x0600) == 0x0400) {
|
|
r |= CR2;
|
|
} else if ((x & 0x0600) == 0x0600) {
|
|
r |= CR3;
|
|
}
|
|
#endif
|
|
#ifdef TABDLY
|
|
if ((x & 0x1800) == 0x0000) {
|
|
r |= TAB0;
|
|
#ifdef TAB1
|
|
} else if ((x & 0x1800) == 0x0800) {
|
|
r |= TAB1;
|
|
#endif
|
|
#ifdef TAB1
|
|
} else if ((x & 0x1800) == 0x1000) {
|
|
r |= TAB2;
|
|
#endif
|
|
} else if ((x & 0x1800) == 0x1800) {
|
|
r |= TAB3;
|
|
}
|
|
#endif
|
|
#ifdef BSDLY
|
|
if ((x & 0x2000) == 0x0000) {
|
|
r |= BS0;
|
|
} else if ((x & 0x2000) == 0x2000) {
|
|
r |= BS1;
|
|
}
|
|
#endif
|
|
#ifdef VTBDLY
|
|
if ((x & 0x4000) == 0x0000) {
|
|
r |= VT0;
|
|
} else if ((x & 0x4000) == 0x4000) {
|
|
r |= VT1;
|
|
}
|
|
#endif
|
|
#ifdef FFBDLY
|
|
if ((x & 0x8000) == 0x0000) {
|
|
r |= FF0;
|
|
} else if ((x & 0x8000) == 0x8000) {
|
|
r |= FF1;
|
|
}
|
|
#endif
|
|
#ifdef OLCUC
|
|
if (x & 0x0002) r |= OLCUC;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static int UnXlatTermiosOflag(int x) {
|
|
int r = 0;
|
|
if (x & OPOST) r |= 0x0001;
|
|
#ifdef ONLCR
|
|
if (x & ONLCR) r |= 0x0004;
|
|
#endif
|
|
#ifdef OCRNL
|
|
if (x & OCRNL) r |= 0x0008;
|
|
#endif
|
|
#ifdef ONOCR
|
|
if (x & ONOCR) r |= 0x0010;
|
|
#endif
|
|
#ifdef ONLRET
|
|
if (x & ONLRET) r |= 0x0020;
|
|
#endif
|
|
#ifdef OFILL
|
|
if (x & OFILL) r |= 0x0040;
|
|
#endif
|
|
#ifdef OFDEL
|
|
if (x & OFDEL) r |= 0x0080;
|
|
#endif
|
|
#ifdef NLDLY
|
|
if ((x & NLDLY) == NL0) {
|
|
r |= 0x0000;
|
|
} else if ((x & NLDLY) == NL1) {
|
|
r |= 0x0100;
|
|
#ifdef NL2
|
|
} else if ((x & NLDLY) == NL2) {
|
|
r |= 0x0000;
|
|
#endif
|
|
#ifdef NL3
|
|
} else if ((x & NLDLY) == NL3) {
|
|
r |= 0x0000;
|
|
#endif
|
|
}
|
|
#endif
|
|
#ifdef CRDLY
|
|
if ((x & CRDLY) == CR0) {
|
|
r |= 0x0000;
|
|
} else if ((x & CRDLY) == CR1) {
|
|
r |= 0x0200;
|
|
} else if ((x & CRDLY) == CR2) {
|
|
r |= 0x0400;
|
|
} else if ((x & CRDLY) == CR3) {
|
|
r |= 0x0600;
|
|
}
|
|
#endif
|
|
#ifdef TABDLY
|
|
if ((x & TABDLY) == TAB0) {
|
|
r |= 0x0000;
|
|
#ifdef TAB1
|
|
} else if ((x & TABDLY) == TAB1) {
|
|
r |= 0x0800;
|
|
#endif
|
|
#ifdef TAB2
|
|
} else if ((x & TABDLY) == TAB2) {
|
|
r |= 0x1000;
|
|
#endif
|
|
} else if ((x & TABDLY) == TAB3) {
|
|
r |= 0x1800;
|
|
}
|
|
#endif
|
|
#ifdef BSDLY
|
|
if ((x & BSDLY) == BS0) {
|
|
r |= 0x0000;
|
|
} else if ((x & BSDLY) == BS1) {
|
|
r |= 0x2000;
|
|
}
|
|
#endif
|
|
#ifdef VTDLY
|
|
if ((x & VTDLY) == VT0) {
|
|
r |= 0x0000;
|
|
} else if ((x & VTDLY) == VT1) {
|
|
r |= 0x4000;
|
|
}
|
|
#endif
|
|
#ifdef FFDLY
|
|
if ((x & FFDLY) == FF0) {
|
|
r |= 0x0000;
|
|
} else if ((x & FFDLY) == FF1) {
|
|
r |= 0x8000;
|
|
}
|
|
#endif
|
|
#ifdef OLCUC
|
|
if (x & OLCUC) r |= 0x0002;
|
|
#endif
|
|
return r;
|
|
}
|
|
|
|
static void XlatTermiosCc(struct termios *dst, const struct termios_bits *src) {
|
|
dst->c_cc[VINTR] = src->c_cc[0];
|
|
dst->c_cc[VQUIT] = src->c_cc[1];
|
|
dst->c_cc[VERASE] = src->c_cc[2];
|
|
dst->c_cc[VKILL] = src->c_cc[3];
|
|
dst->c_cc[VEOF] = src->c_cc[4];
|
|
dst->c_cc[VTIME] = src->c_cc[5];
|
|
dst->c_cc[VMIN] = src->c_cc[6];
|
|
dst->c_cc[VSTART] = src->c_cc[8];
|
|
dst->c_cc[VSTOP] = src->c_cc[9];
|
|
dst->c_cc[VSUSP] = src->c_cc[10];
|
|
dst->c_cc[VEOL] = src->c_cc[11];
|
|
#ifdef VSWTC
|
|
dst->c_cc[VSWTC] = src->c_cc[7];
|
|
#endif
|
|
#ifdef VREPRINT
|
|
dst->c_cc[VREPRINT] = src->c_cc[12];
|
|
#endif
|
|
#ifdef VDISCARD
|
|
dst->c_cc[VDISCARD] = src->c_cc[13];
|
|
#endif
|
|
#ifdef VWERASE
|
|
dst->c_cc[VWERASE] = src->c_cc[14];
|
|
#endif
|
|
#ifdef VLNEXT
|
|
dst->c_cc[VLNEXT] = src->c_cc[15];
|
|
#endif
|
|
#ifdef VEOL2
|
|
dst->c_cc[VEOL2] = src->c_cc[16];
|
|
#endif
|
|
}
|
|
|
|
static void UnXlatTermiosCc(struct termios_bits *dst,
|
|
const struct termios *src) {
|
|
dst->c_cc[0] = src->c_cc[VINTR];
|
|
dst->c_cc[1] = src->c_cc[VQUIT];
|
|
dst->c_cc[2] = src->c_cc[VERASE];
|
|
dst->c_cc[3] = src->c_cc[VKILL];
|
|
dst->c_cc[4] = src->c_cc[VEOF];
|
|
dst->c_cc[5] = src->c_cc[VTIME];
|
|
dst->c_cc[6] = src->c_cc[VMIN];
|
|
dst->c_cc[8] = src->c_cc[VSTART];
|
|
dst->c_cc[9] = src->c_cc[VSTOP];
|
|
dst->c_cc[10] = src->c_cc[VSUSP];
|
|
dst->c_cc[11] = src->c_cc[VEOL];
|
|
#ifdef VSWTC
|
|
dst->c_cc[7] = src->c_cc[VSWTC];
|
|
#endif
|
|
#ifdef VREPRINT
|
|
dst->c_cc[12] = src->c_cc[VREPRINT];
|
|
#endif
|
|
#ifdef VDISCARD
|
|
dst->c_cc[13] = src->c_cc[VDISCARD];
|
|
#endif
|
|
#ifdef VWERASE
|
|
dst->c_cc[14] = src->c_cc[VWERASE];
|
|
#endif
|
|
#ifdef VLNEXT
|
|
dst->c_cc[15] = src->c_cc[VLNEXT];
|
|
#endif
|
|
#ifdef VEOL2
|
|
dst->c_cc[16] = src->c_cc[VEOL2];
|
|
#endif
|
|
}
|
|
|
|
void XlatLinuxToTermios(struct termios *dst, const struct termios_bits *src) {
|
|
memset(dst, 0, sizeof(*dst));
|
|
dst->c_iflag = XlatTermiosIflag(Read32(src->c_iflag));
|
|
dst->c_oflag = XlatTermiosOflag(Read32(src->c_oflag));
|
|
dst->c_cflag = XlatTermiosCflag(Read32(src->c_cflag));
|
|
dst->c_lflag = XlatTermiosLflag(Read32(src->c_lflag));
|
|
XlatTermiosCc(dst, src);
|
|
}
|
|
|
|
void XlatTermiosToLinux(struct termios_bits *dst, const struct termios *src) {
|
|
memset(dst, 0, sizeof(*dst));
|
|
Write32(dst->c_iflag, UnXlatTermiosIflag(src->c_iflag));
|
|
Write32(dst->c_oflag, UnXlatTermiosOflag(src->c_oflag));
|
|
Write32(dst->c_cflag, UnXlatTermiosCflag(src->c_cflag));
|
|
Write32(dst->c_lflag, UnXlatTermiosLflag(src->c_lflag));
|
|
UnXlatTermiosCc(dst, src);
|
|
}
|