mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-30 14:30:27 +00:00
Fix bugs in termios library and cleanup code
This change fixes an issue with the tcflow() magic numbers that was causing bash to freeze up on Linux. While auditing termios polyfills, several other issues were identified with XNU/BSD compatibility. Out of an abundance of caution this change undefines as much surface area from libc/calls/struct/termios.h as possible, so that autoconf scripts are less likely to detect non-POSIX teletypewriter APIs that haven't been polyfilled by Cosmopolitan. This is a *breaking change* for your static archives in /opt/cosmos if you use the cosmocc toolchain. That's because this change disables the ioctl() undiamonding trick for code outside the monorepo, specifically because it'll lead to brittle ABI breakages like this. If you're using the cosmocc toolchain, you'll need to rebuild libraries like ncurses, readline, etc. Yes diamonds cause bloat. To work around that, consider using tcgetwinsize() instead of ioctl(TIOCGWINSZ) since it'll help you avoid pulling every single ioctl-related polyfill into the linkage. The cosmocc script was specifying -DNDEBUG for some reason. It's fixed.
This commit is contained in:
parent
06b749ae03
commit
4778cd4d27
187 changed files with 1025 additions and 1848 deletions
|
@ -27,6 +27,7 @@
|
|||
#include "libc/calls/struct/stat.h"
|
||||
#include "libc/calls/struct/timeval.h"
|
||||
#include "libc/calls/struct/winsize.h"
|
||||
#include "libc/calls/termios.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
|
@ -334,7 +335,7 @@ int GetTerminalWidth(void) {
|
|||
return atoi(s);
|
||||
} else {
|
||||
ws.ws_col = 0;
|
||||
ioctl(2, TIOCGWINSZ, &ws);
|
||||
tcgetwinsize(2, &ws);
|
||||
return ws.ws_col;
|
||||
}
|
||||
}
|
||||
|
@ -348,7 +349,7 @@ int GetLineWidth(bool *isineditor) {
|
|||
}
|
||||
if (s) {
|
||||
return atoi(s);
|
||||
} else if (ioctl(2, TIOCGWINSZ, &ws) != -1) {
|
||||
} else if (tcgetwinsize(2, &ws) != -1) {
|
||||
if (ws.ws_col && ws.ws_row) {
|
||||
return ws.ws_col * ws.ws_row / 3;
|
||||
} else {
|
||||
|
|
|
@ -1,166 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_TOOL_BUILD_LIB_BITS_H_
|
||||
#define COSMOPOLITAN_TOOL_BUILD_LIB_BITS_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct iovec_bits {
|
||||
uint8_t iov_base[8];
|
||||
uint8_t iov_len[8];
|
||||
};
|
||||
|
||||
struct pollfd_bits {
|
||||
uint8_t fd[4];
|
||||
uint8_t events[2];
|
||||
uint8_t revents[2];
|
||||
};
|
||||
|
||||
struct timeval_bits {
|
||||
uint8_t tv_sec[8];
|
||||
uint8_t tv_usec[8];
|
||||
};
|
||||
|
||||
struct timespec_bits {
|
||||
uint8_t tv_sec[8];
|
||||
uint8_t tv_nsec[8];
|
||||
};
|
||||
|
||||
struct timezone_bits {
|
||||
uint8_t tz_minuteswest[4];
|
||||
uint8_t tz_dsttime[4];
|
||||
};
|
||||
|
||||
struct sigaction_bits {
|
||||
uint8_t handler[8];
|
||||
uint8_t flags[8];
|
||||
uint8_t restorer[8];
|
||||
uint8_t mask[8];
|
||||
};
|
||||
|
||||
struct winsize_bits {
|
||||
uint8_t ws_row[2];
|
||||
uint8_t ws_col[2];
|
||||
uint8_t ws_xpixel[2];
|
||||
uint8_t ws_ypixel[2];
|
||||
};
|
||||
|
||||
struct termios_bits {
|
||||
uint8_t c_iflag[4];
|
||||
uint8_t c_oflag[4];
|
||||
uint8_t c_cflag[4];
|
||||
uint8_t c_lflag[4];
|
||||
uint8_t c_cc[32];
|
||||
uint8_t c_ispeed[4];
|
||||
uint8_t c_ospeed[4];
|
||||
};
|
||||
|
||||
struct sockaddr_in_bits {
|
||||
uint8_t sin_family[2];
|
||||
uint16_t sin_port;
|
||||
uint32_t sin_addr;
|
||||
uint8_t sin_zero[8];
|
||||
};
|
||||
|
||||
struct stat_bits {
|
||||
uint8_t st_dev[8];
|
||||
uint8_t st_ino[8];
|
||||
uint8_t st_nlink[8];
|
||||
uint8_t st_mode[4];
|
||||
uint8_t st_uid[4];
|
||||
uint8_t st_gid[4];
|
||||
uint8_t __pad[4];
|
||||
uint8_t st_rdev[8];
|
||||
uint8_t st_size[8];
|
||||
uint8_t st_blksize[8];
|
||||
uint8_t st_blocks[8];
|
||||
struct timespec_bits st_atim;
|
||||
struct timespec_bits st_mtim;
|
||||
struct timespec_bits st_ctim;
|
||||
};
|
||||
|
||||
struct itimerval_bits {
|
||||
struct timeval_bits it_interval;
|
||||
struct timeval_bits it_value;
|
||||
};
|
||||
|
||||
struct rusage_bits {
|
||||
struct timeval_bits ru_utime;
|
||||
struct timeval_bits ru_stime;
|
||||
uint8_t ru_maxrss[8];
|
||||
uint8_t ru_ixrss[8];
|
||||
uint8_t ru_idrss[8];
|
||||
uint8_t ru_isrss[8];
|
||||
uint8_t ru_minflt[8];
|
||||
uint8_t ru_majflt[8];
|
||||
uint8_t ru_nswap[8];
|
||||
uint8_t ru_inblock[8];
|
||||
uint8_t ru_oublock[8];
|
||||
uint8_t ru_msgsnd[8];
|
||||
uint8_t ru_msgrcv[8];
|
||||
uint8_t ru_nsignals[8];
|
||||
uint8_t ru_nvcsw[8];
|
||||
uint8_t ru_nivcsw[8];
|
||||
};
|
||||
|
||||
struct siginfo_bits {
|
||||
uint8_t si_signo[4];
|
||||
uint8_t si_errno[4];
|
||||
uint8_t si_code[4];
|
||||
uint8_t __pad[4];
|
||||
uint8_t payload[112];
|
||||
};
|
||||
|
||||
struct fpstate_bits {
|
||||
uint8_t cwd[2];
|
||||
uint8_t swd[2];
|
||||
uint8_t ftw[2];
|
||||
uint8_t fop[2];
|
||||
uint8_t rip[8];
|
||||
uint8_t rdp[8];
|
||||
uint8_t mxcsr[4];
|
||||
uint8_t mxcr_mask[4];
|
||||
uint8_t st[8][16];
|
||||
uint8_t xmm[16][16];
|
||||
uint8_t __padding[96];
|
||||
};
|
||||
|
||||
struct ucontext_bits {
|
||||
uint8_t uc_flags[8];
|
||||
uint8_t uc_link[8];
|
||||
uint8_t ss_sp[8];
|
||||
uint8_t ss_flags[4];
|
||||
uint8_t __pad0[4];
|
||||
uint8_t ss_size[8];
|
||||
uint8_t r8[8];
|
||||
uint8_t r9[8];
|
||||
uint8_t r10[8];
|
||||
uint8_t r11[8];
|
||||
uint8_t r12[8];
|
||||
uint8_t r13[8];
|
||||
uint8_t r14[8];
|
||||
uint8_t r15[8];
|
||||
uint8_t rdi[8];
|
||||
uint8_t rsi[8];
|
||||
uint8_t rbp[8];
|
||||
uint8_t rbx[8];
|
||||
uint8_t rdx[8];
|
||||
uint8_t rax[8];
|
||||
uint8_t rcx[8];
|
||||
uint8_t rsp[8];
|
||||
uint8_t rip[8];
|
||||
uint8_t eflags[8];
|
||||
uint8_t cs[2];
|
||||
uint8_t gs[2];
|
||||
uint8_t fs[2];
|
||||
uint8_t ss[2];
|
||||
uint8_t err[8];
|
||||
uint8_t trapno[8];
|
||||
uint8_t oldmask[8];
|
||||
uint8_t cr2[8];
|
||||
uint8_t fpstate[8];
|
||||
uint8_t __pad1[64];
|
||||
uint8_t uc_sigmask[8];
|
||||
};
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_TOOL_BUILD_LIB_BITS_H_ */
|
|
@ -27,8 +27,6 @@
|
|||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/at.h"
|
||||
#include "libc/sysv/consts/ex.h"
|
||||
#include "libc/sysv/consts/exit.h"
|
||||
#include "libc/sysv/consts/ok.h"
|
||||
#include "libc/sysv/consts/s.h"
|
||||
#include "libc/x/x.h"
|
||||
|
@ -63,6 +61,30 @@ char linkbuf[PATH_MAX];
|
|||
|
||||
void Mv(char *, char *);
|
||||
|
||||
nullterminated() void Print(int fd, const char *s, ...) {
|
||||
va_list va;
|
||||
char buf[2048];
|
||||
va_start(va, s);
|
||||
buf[0] = 0;
|
||||
do {
|
||||
strlcat(buf, s, sizeof(buf));
|
||||
} while ((s = va_arg(va, const char *)));
|
||||
write(fd, buf, strlen(buf));
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
wontreturn void Die(const char *path, const char *reason) {
|
||||
Print(2, path, ": ", reason, "\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
wontreturn void SysExit(const char *path, const char *func) {
|
||||
const char *errstr;
|
||||
if (!(errstr = _strerdoc(errno))) errstr = "EUNKNOWN";
|
||||
Print(2, path, ": ", func, "() failed with ", errstr, "\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bool IsDirectory(const char *path) {
|
||||
int e;
|
||||
bool res;
|
||||
|
@ -84,10 +106,8 @@ bool IsSymlink(const char *path) {
|
|||
return res;
|
||||
}
|
||||
|
||||
wontreturn void PrintUsage(int rc, FILE *f) {
|
||||
fputs("usage: ", f);
|
||||
fputs(prog, f);
|
||||
fputs(USAGE, f);
|
||||
wontreturn void PrintUsage(int rc, int fd) {
|
||||
Print(fd, "usage: ", prog, USAGE, NULL);
|
||||
exit(rc);
|
||||
}
|
||||
|
||||
|
@ -104,9 +124,9 @@ void GetOpts(int argc, char *argv[]) {
|
|||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
PrintUsage(EXIT_SUCCESS, stdout);
|
||||
PrintUsage(0, 1);
|
||||
default:
|
||||
PrintUsage(EX_USAGE, stderr);
|
||||
PrintUsage(1, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,9 +151,7 @@ int Visit(const char *fpath, const struct stat *sb, int tflag,
|
|||
Mv(srcfile, dstfile);
|
||||
return 0;
|
||||
default:
|
||||
fputs(fpath, stderr);
|
||||
fputs(": can't handle file type\n", stderr);
|
||||
exit(1);
|
||||
Die(fpath, "can't handle file type");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,7 +160,7 @@ char *Join(const char *a, const char *b) {
|
|||
n = strlen(a);
|
||||
m = strlen(b);
|
||||
if (n + 1 + m + 1 > sizeof(dstfile)) {
|
||||
fputs("error: mv: path too long\n", stderr);
|
||||
Print(2, "error: mv: path too long\n", NULL);
|
||||
exit(1);
|
||||
}
|
||||
stpcpy(stpcpy(stpcpy(dstfile, a), "/"), b);
|
||||
|
@ -151,16 +169,14 @@ char *Join(const char *a, const char *b) {
|
|||
|
||||
void Mv(char *src, char *dst) {
|
||||
ssize_t rc;
|
||||
const char *s;
|
||||
const char *s, *d;
|
||||
if (strlen(src) + 1 > PATH_MAX) _Exit(2);
|
||||
if (strlen(dst) + 1 > PATH_MAX) _Exit(2);
|
||||
basename(src);
|
||||
basename(dst);
|
||||
if (IsDirectory(src)) {
|
||||
if (!recursive) {
|
||||
fputs(prog, stderr);
|
||||
fputs(": won't move directory without -r flag.\n", stderr);
|
||||
exit(1);
|
||||
Die(prog, "won't move directory without -r flag.");
|
||||
}
|
||||
strcpy(dstdir, dst);
|
||||
if (IsDirectory(dst)) {
|
||||
|
@ -175,46 +191,40 @@ void Mv(char *src, char *dst) {
|
|||
strcpy(srcdir, "");
|
||||
}
|
||||
if (nftw(src, Visit, 20, 0) == -1) {
|
||||
fputs(prog, stderr);
|
||||
fputs(": nftw failed: ", stderr);
|
||||
fputs(_strerdoc(errno), stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
SysExit(src, "nftw");
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (IsDirectory(dst)) {
|
||||
dst = Join(dst, basename(src));
|
||||
}
|
||||
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) goto OnFail;
|
||||
strcpy(mkbuf, dst);
|
||||
if (makedirs(dirname(mkbuf), 0755) == -1) goto OnFail;
|
||||
if (IsSymlink(src)) {
|
||||
if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) goto OnFail;
|
||||
linkbuf[rc] = 0;
|
||||
if (symlink(linkbuf, dst) == -1) goto OnFail;
|
||||
} else {
|
||||
if (rename(src, dst) == -1) goto OnFail;
|
||||
if (!force && access(dst, W_OK) == -1 && errno != ENOENT) {
|
||||
SysExit(dst, "access");
|
||||
}
|
||||
strcpy(mkbuf, dst);
|
||||
if (makedirs((d = dirname(mkbuf)), 0755) == -1) {
|
||||
SysExit(d, "makedirs");
|
||||
}
|
||||
if (IsSymlink(src)) {
|
||||
if ((rc = readlink(src, linkbuf, sizeof(linkbuf) - 1)) == -1) {
|
||||
SysExit(src, "readlink");
|
||||
}
|
||||
linkbuf[rc] = 0;
|
||||
if (symlink(linkbuf, dst)) {
|
||||
SysExit(dst, "symlink");
|
||||
}
|
||||
} else {
|
||||
if (rename(src, dst)) {
|
||||
SysExit(src, "rename");
|
||||
}
|
||||
}
|
||||
return;
|
||||
OnFail:
|
||||
s = _strerdoc(errno);
|
||||
fputs(prog, stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs(src, stderr);
|
||||
fputs(" ", stderr);
|
||||
fputs(dst, stderr);
|
||||
fputs(": ", stderr);
|
||||
fputs(s, stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
prog = argc > 0 ? argv[0] : "mv.com";
|
||||
GetOpts(argc, argv);
|
||||
if (argc - optind < 2) PrintUsage(EX_USAGE, stderr);
|
||||
if (argc - optind < 2) PrintUsage(1, 2);
|
||||
for (i = optind; i < argc - 1; ++i) {
|
||||
Mv(argv[i], argv[argc - 1]);
|
||||
}
|
||||
|
|
|
@ -188,14 +188,11 @@ static void CopyZip(void) {
|
|||
ldest += length;
|
||||
// write directory entry
|
||||
length = ZIP_CFILE_HDRSIZE(cfile);
|
||||
if (READ32LE(cfile) != kZipCfileHdrMagic) notpossible;
|
||||
if (pwrite(outfd, cfile, length, cdest) != length) {
|
||||
SysExit(outpath, "lfile pwrite");
|
||||
}
|
||||
cdest += length;
|
||||
}
|
||||
if (ldest != outsize + ltotal) __builtin_trap();
|
||||
if (cdest != outsize + ltotal + ctotal) __builtin_trap();
|
||||
WRITE32LE(eocd + kZipCdirOffsetOffset, outsize + ltotal);
|
||||
length = ZIP_CDIR_HDRSIZE(eocd);
|
||||
if (pwrite(outfd, eocd, length, cdest) != length) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue