mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
Add script.com and whois.com courtesy of FreeBSD
This commit is contained in:
parent
654ceaba7d
commit
1ad2f530f9
33 changed files with 1735 additions and 265 deletions
522
examples/script.c
Normal file
522
examples/script.c
Normal file
|
@ -0,0 +1,522 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright (c) 2010, 2012 David E. O'Brien │
|
||||||
|
│ Copyright (c) 1980, 1992, 1993 │
|
||||||
|
│ The Regents of the University of California. All rights reserved. │
|
||||||
|
│ │
|
||||||
|
│ Redistribution and use in source and binary forms, with or without │
|
||||||
|
│ modification, are permitted provided that the following conditions │
|
||||||
|
│ are met: │
|
||||||
|
│ 1. Redistributions of source code must retain the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer. │
|
||||||
|
│ 2. Redistributions in binary form must reproduce the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer in the │
|
||||||
|
│ documentation and/or other materials provided with the distribution. │
|
||||||
|
│ 3. Neither the name of the University nor the names of its contributors │
|
||||||
|
│ may be used to endorse or promote products derived from this software │
|
||||||
|
│ without specific prior written permission. │
|
||||||
|
│ │
|
||||||
|
│ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND │
|
||||||
|
│ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE │
|
||||||
|
│ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE │
|
||||||
|
│ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE │
|
||||||
|
│ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS │
|
||||||
|
│ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) │
|
||||||
|
│ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT │
|
||||||
|
│ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY │
|
||||||
|
│ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF │
|
||||||
|
│ SUCH DAMAGE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/struct/iovec.h"
|
||||||
|
#include "libc/calls/struct/stat.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
|
#include "libc/calls/struct/timeval.h"
|
||||||
|
#include "libc/calls/struct/winsize.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/calls/weirdtypes.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/fmt/conv.h"
|
||||||
|
#include "libc/intrin/bswap.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/log/bsd.h"
|
||||||
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/paths.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/sock/select.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/sysv/consts/fileno.h"
|
||||||
|
#include "libc/sysv/consts/s.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
#include "libc/time/time.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Terminal Screencast Recorder / Player, e.g.
|
||||||
|
*
|
||||||
|
* make o//examples/script.com
|
||||||
|
* o//examples/script.com -r
|
||||||
|
* # type stuff..
|
||||||
|
* # CTRL-D
|
||||||
|
* o//examples/script.com -p typescript
|
||||||
|
*
|
||||||
|
* @note works on Linux, OpenBSD, NetBSD, FreeBSD, MacOS
|
||||||
|
* @see https://asciinema.org/
|
||||||
|
*/
|
||||||
|
|
||||||
|
asm(".ident\t\"\\n\\n\
|
||||||
|
FreeBSD Script (BSD-3 License)\\n\
|
||||||
|
Copyright (c) 2010, 2012 David E. O'Brien\\n\
|
||||||
|
Copyright (c) 1980, 1992, 1993\\n\
|
||||||
|
\tThe Regents of the University of California.\\n\
|
||||||
|
\tAll rights reserved.\"");
|
||||||
|
asm(".include \"libc/disclaimer.inc\"");
|
||||||
|
|
||||||
|
#define DEF_BUF 65536
|
||||||
|
|
||||||
|
struct stamp {
|
||||||
|
uint64_t scr_len; /* amount of data */
|
||||||
|
uint64_t scr_sec; /* time it arrived in seconds... */
|
||||||
|
uint32_t scr_usec; /* ...and microseconds */
|
||||||
|
uint32_t scr_direction; /* 'i', 'o', etc (also indicates endianness) */
|
||||||
|
};
|
||||||
|
|
||||||
|
static FILE *fscript;
|
||||||
|
static int master, slave;
|
||||||
|
static int child;
|
||||||
|
static const char *fname;
|
||||||
|
static char *fmfname;
|
||||||
|
static int qflg, ttyflg;
|
||||||
|
static int usesleep, rawout, showexit;
|
||||||
|
|
||||||
|
static struct termios tt;
|
||||||
|
|
||||||
|
static void done(int) wontreturn;
|
||||||
|
static void doshell(char **);
|
||||||
|
static void finish(void);
|
||||||
|
static void record(FILE *, char *, size_t, int);
|
||||||
|
static void consume(FILE *, off_t, char *, int);
|
||||||
|
static void playback(FILE *) wontreturn;
|
||||||
|
static void usage(void);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int cc;
|
||||||
|
struct termios rtt, stt;
|
||||||
|
struct winsize win;
|
||||||
|
struct timeval tv, *tvp;
|
||||||
|
time_t tvec, start;
|
||||||
|
static char obuf[BUFSIZ];
|
||||||
|
static char ibuf[BUFSIZ];
|
||||||
|
fd_set rfd;
|
||||||
|
int aflg, Fflg, kflg, pflg, ch, k, n;
|
||||||
|
int flushtime, readstdin;
|
||||||
|
int fm_fd, fm_log;
|
||||||
|
|
||||||
|
aflg = Fflg = kflg = pflg = 0;
|
||||||
|
usesleep = 1;
|
||||||
|
rawout = 0;
|
||||||
|
flushtime = 30;
|
||||||
|
fm_fd = -1; /* Shut up stupid "may be used uninitialized" GCC
|
||||||
|
warning. (not needed w/clang) */
|
||||||
|
showexit = 0;
|
||||||
|
|
||||||
|
while ((ch = getopt(argc, argv, "adeFfkpqrt:")) != -1)
|
||||||
|
switch(ch) {
|
||||||
|
case 'a':
|
||||||
|
aflg = 1;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
usesleep = 0;
|
||||||
|
break;
|
||||||
|
case 'e': /* Default behavior, accepted for linux compat */
|
||||||
|
break;
|
||||||
|
case 'F':
|
||||||
|
Fflg = 1;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
kflg = 1;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
pflg = 1;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
qflg = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
rawout = 1;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
flushtime = atoi(optarg);
|
||||||
|
if (flushtime < 0)
|
||||||
|
err(1, "invalid flush time %d", flushtime);
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
fname = argv[0];
|
||||||
|
argv++;
|
||||||
|
argc--;
|
||||||
|
} else
|
||||||
|
fname = "typescript";
|
||||||
|
|
||||||
|
if ((fscript = fopen(fname, pflg ? "r" : aflg ? "a" : "w")) == NULL)
|
||||||
|
err(1, "%s", fname);
|
||||||
|
|
||||||
|
if (pflg)
|
||||||
|
playback(fscript);
|
||||||
|
|
||||||
|
if (tcgetattr(STDIN_FILENO, &tt) == -1 ||
|
||||||
|
ioctl(STDIN_FILENO, TIOCGWINSZ, &win) == -1) {
|
||||||
|
if (errno != ENOTTY) /* For debugger. */
|
||||||
|
err(1, "tcgetattr/ioctl");
|
||||||
|
if (openpty(&master, &slave, NULL, NULL, NULL) == -1)
|
||||||
|
err(1, "openpty");
|
||||||
|
} else {
|
||||||
|
if (openpty(&master, &slave, NULL, &tt, &win) == -1)
|
||||||
|
err(1, "openpty");
|
||||||
|
ttyflg = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawout)
|
||||||
|
record(fscript, NULL, 0, 's');
|
||||||
|
|
||||||
|
if (!qflg) {
|
||||||
|
tvec = time(NULL);
|
||||||
|
printf("Script started, output file is %s\n", fname);
|
||||||
|
if (!rawout) {
|
||||||
|
fprintf(fscript, "Script started on %s",
|
||||||
|
ctime(&tvec));
|
||||||
|
if (argv[0]) {
|
||||||
|
showexit = 1;
|
||||||
|
fprintf(fscript, "Command: ");
|
||||||
|
for (k = 0 ; argv[k] ; ++k)
|
||||||
|
fprintf(fscript, "%s%s", k ? " " : "",
|
||||||
|
argv[k]);
|
||||||
|
fprintf(fscript, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fflush(fscript);
|
||||||
|
}
|
||||||
|
if (ttyflg) {
|
||||||
|
rtt = tt;
|
||||||
|
cfmakeraw(&rtt);
|
||||||
|
rtt.c_lflag &= ~ECHO;
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
|
||||||
|
}
|
||||||
|
|
||||||
|
child = fork();
|
||||||
|
if (child < 0) {
|
||||||
|
warn("fork");
|
||||||
|
done(1);
|
||||||
|
}
|
||||||
|
if (child == 0) {
|
||||||
|
doshell(argv);
|
||||||
|
}
|
||||||
|
close(slave);
|
||||||
|
|
||||||
|
start = tvec = time(0);
|
||||||
|
readstdin = 1;
|
||||||
|
for (;;) {
|
||||||
|
FD_ZERO(&rfd);
|
||||||
|
FD_SET(master, &rfd);
|
||||||
|
if (readstdin)
|
||||||
|
FD_SET(STDIN_FILENO, &rfd);
|
||||||
|
if (!readstdin && ttyflg) {
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
tvp = &tv;
|
||||||
|
readstdin = 1;
|
||||||
|
} else if (flushtime > 0) {
|
||||||
|
tv.tv_sec = flushtime - (tvec - start);
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
tvp = &tv;
|
||||||
|
} else {
|
||||||
|
tvp = NULL;
|
||||||
|
}
|
||||||
|
n = select(master + 1, &rfd, 0, 0, tvp);
|
||||||
|
if (n < 0 && errno != EINTR)
|
||||||
|
break;
|
||||||
|
if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
|
||||||
|
cc = read(STDIN_FILENO, ibuf, BUFSIZ);
|
||||||
|
if (cc < 0)
|
||||||
|
break;
|
||||||
|
if (cc == 0) {
|
||||||
|
if (tcgetattr(master, &stt) == 0 &&
|
||||||
|
(stt.c_lflag & ICANON) != 0) {
|
||||||
|
write(master, &stt.c_cc[VEOF], 1);
|
||||||
|
}
|
||||||
|
readstdin = 0;
|
||||||
|
}
|
||||||
|
if (cc > 0) {
|
||||||
|
if (rawout)
|
||||||
|
record(fscript, ibuf, cc, 'i');
|
||||||
|
write(master, ibuf, cc);
|
||||||
|
if (kflg && tcgetattr(master, &stt) >= 0 &&
|
||||||
|
((stt.c_lflag & ECHO) == 0)) {
|
||||||
|
fwrite(ibuf, 1, cc, fscript);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n > 0 && FD_ISSET(master, &rfd)) {
|
||||||
|
cc = read(master, obuf, sizeof (obuf));
|
||||||
|
if (cc <= 0)
|
||||||
|
break;
|
||||||
|
write(STDOUT_FILENO, obuf, cc);
|
||||||
|
if (rawout)
|
||||||
|
record(fscript, obuf, cc, 'o');
|
||||||
|
else
|
||||||
|
fwrite(obuf, 1, cc, fscript);
|
||||||
|
}
|
||||||
|
tvec = time(0);
|
||||||
|
if (tvec - start >= flushtime) {
|
||||||
|
fflush(fscript);
|
||||||
|
start = tvec;
|
||||||
|
}
|
||||||
|
if (Fflg)
|
||||||
|
fflush(fscript);
|
||||||
|
}
|
||||||
|
finish();
|
||||||
|
done(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"usage: script [-adfkpqr] [-t time] [file [command ...]]\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
finish(void)
|
||||||
|
{
|
||||||
|
int e, status;
|
||||||
|
|
||||||
|
if (waitpid(child, &status, 0) == child) {
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
e = WEXITSTATUS(status);
|
||||||
|
else if (WIFSIGNALED(status))
|
||||||
|
e = WTERMSIG(status);
|
||||||
|
else /* can't happen */
|
||||||
|
e = 1;
|
||||||
|
done(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
doshell(char **av)
|
||||||
|
{
|
||||||
|
const char *shell;
|
||||||
|
|
||||||
|
shell = getenv("SHELL");
|
||||||
|
if (shell == NULL)
|
||||||
|
shell = _PATH_BSHELL;
|
||||||
|
|
||||||
|
close(master);
|
||||||
|
fclose(fscript);
|
||||||
|
free(fmfname);
|
||||||
|
login_tty(slave);
|
||||||
|
setenv("SCRIPT", fname, 1);
|
||||||
|
if (av[0]) {
|
||||||
|
execvp(av[0], av);
|
||||||
|
warn("%s", av[0]);
|
||||||
|
} else {
|
||||||
|
execl(shell, shell, "-i", 0);
|
||||||
|
warn("%s", shell);
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
done(int eno)
|
||||||
|
{
|
||||||
|
time_t tvec;
|
||||||
|
|
||||||
|
if (ttyflg)
|
||||||
|
tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
|
||||||
|
tvec = time(NULL);
|
||||||
|
if (rawout)
|
||||||
|
record(fscript, NULL, 0, 'e');
|
||||||
|
if (!qflg) {
|
||||||
|
if (!rawout) {
|
||||||
|
if (showexit)
|
||||||
|
fprintf(fscript, "\nCommand exit status:"
|
||||||
|
" %d", eno);
|
||||||
|
fprintf(fscript,"\nScript done on %s",
|
||||||
|
ctime(&tvec));
|
||||||
|
}
|
||||||
|
printf("\nScript done, output file is %s\n", fname);
|
||||||
|
}
|
||||||
|
fclose(fscript);
|
||||||
|
close(master);
|
||||||
|
exit(eno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
record(FILE *fp, char *buf, size_t cc, int direction)
|
||||||
|
{
|
||||||
|
struct iovec iov[2];
|
||||||
|
struct stamp stamp;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
stamp.scr_len = cc;
|
||||||
|
stamp.scr_sec = tv.tv_sec;
|
||||||
|
stamp.scr_usec = tv.tv_usec;
|
||||||
|
stamp.scr_direction = direction;
|
||||||
|
iov[0].iov_len = sizeof(stamp);
|
||||||
|
iov[0].iov_base = &stamp;
|
||||||
|
iov[1].iov_len = cc;
|
||||||
|
iov[1].iov_base = buf;
|
||||||
|
if (writev(fileno(fp), &iov[0], 2) == -1)
|
||||||
|
err(1, "writev");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
consume(FILE *fp, off_t len, char *buf, int reg)
|
||||||
|
{
|
||||||
|
size_t l;
|
||||||
|
|
||||||
|
if (reg) {
|
||||||
|
if (fseeko(fp, len, SEEK_CUR) == -1)
|
||||||
|
err(1, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (len > 0) {
|
||||||
|
l = MIN(DEF_BUF, len);
|
||||||
|
if (fread(buf, sizeof(char), l, fp) != l)
|
||||||
|
err(1, "cannot read buffer");
|
||||||
|
len -= l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define swapstamp(stamp) do { \
|
||||||
|
if (stamp.scr_direction > 0xff) { \
|
||||||
|
stamp.scr_len = bswap_64(stamp.scr_len); \
|
||||||
|
stamp.scr_sec = bswap_64(stamp.scr_sec); \
|
||||||
|
stamp.scr_usec = bswap_32(stamp.scr_usec); \
|
||||||
|
stamp.scr_direction = bswap_32(stamp.scr_direction); \
|
||||||
|
} \
|
||||||
|
} while (0/*CONSTCOND*/)
|
||||||
|
|
||||||
|
static void
|
||||||
|
termset(void)
|
||||||
|
{
|
||||||
|
struct termios traw;
|
||||||
|
|
||||||
|
if (tcgetattr(STDOUT_FILENO, &tt) == -1) {
|
||||||
|
if (errno != ENOTTY) /* For debugger. */
|
||||||
|
err(1, "tcgetattr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ttyflg = 1;
|
||||||
|
traw = tt;
|
||||||
|
cfmakeraw(&traw);
|
||||||
|
traw.c_lflag |= ISIG;
|
||||||
|
tcsetattr(STDOUT_FILENO, TCSANOW, &traw);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
termreset(void)
|
||||||
|
{
|
||||||
|
if (ttyflg) {
|
||||||
|
tcsetattr(STDOUT_FILENO, TCSADRAIN, &tt);
|
||||||
|
ttyflg = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
playback(FILE *fp)
|
||||||
|
{
|
||||||
|
struct timespec tsi, tso;
|
||||||
|
struct stamp stamp;
|
||||||
|
struct stat pst;
|
||||||
|
static char buf[DEF_BUF];
|
||||||
|
off_t nread, save_len;
|
||||||
|
size_t l;
|
||||||
|
time_t tclock;
|
||||||
|
int reg;
|
||||||
|
|
||||||
|
if (fstat(fileno(fp), &pst) == -1)
|
||||||
|
err(1, "fstat failed");
|
||||||
|
|
||||||
|
reg = S_ISREG(pst.st_mode);
|
||||||
|
|
||||||
|
for (nread = 0; !reg || nread < pst.st_size; nread += save_len) {
|
||||||
|
if (fread(&stamp, sizeof(stamp), 1, fp) != 1) {
|
||||||
|
if (reg)
|
||||||
|
err(1, "reading playback header");
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
swapstamp(stamp);
|
||||||
|
save_len = sizeof(stamp);
|
||||||
|
|
||||||
|
if (reg && stamp.scr_len >
|
||||||
|
(uint64_t)(pst.st_size - save_len) - nread)
|
||||||
|
errx(1, "invalid stamp");
|
||||||
|
|
||||||
|
save_len += stamp.scr_len;
|
||||||
|
tclock = stamp.scr_sec;
|
||||||
|
tso.tv_sec = stamp.scr_sec;
|
||||||
|
tso.tv_nsec = stamp.scr_usec * 1000;
|
||||||
|
|
||||||
|
switch (stamp.scr_direction) {
|
||||||
|
case 's':
|
||||||
|
if (!qflg)
|
||||||
|
printf("Script started on %s",
|
||||||
|
ctime(&tclock));
|
||||||
|
tsi = tso;
|
||||||
|
consume(fp, stamp.scr_len, buf, reg);
|
||||||
|
termset();
|
||||||
|
atexit(termreset);
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
termreset();
|
||||||
|
if (!qflg)
|
||||||
|
printf("\nScript done on %s",
|
||||||
|
ctime(&tclock));
|
||||||
|
consume(fp, stamp.scr_len, buf, reg);
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
/* throw input away */
|
||||||
|
consume(fp, stamp.scr_len, buf, reg);
|
||||||
|
break;
|
||||||
|
case 'o':
|
||||||
|
tsi.tv_sec = tso.tv_sec - tsi.tv_sec;
|
||||||
|
tsi.tv_nsec = tso.tv_nsec - tsi.tv_nsec;
|
||||||
|
if (tsi.tv_nsec < 0) {
|
||||||
|
tsi.tv_sec -= 1;
|
||||||
|
tsi.tv_nsec += 1000000000;
|
||||||
|
}
|
||||||
|
if (usesleep)
|
||||||
|
nanosleep(&tsi, NULL);
|
||||||
|
tsi = tso;
|
||||||
|
while (stamp.scr_len > 0) {
|
||||||
|
l = MIN(DEF_BUF, stamp.scr_len);
|
||||||
|
if (fread(buf, sizeof(char), l, fp) != l)
|
||||||
|
err(1, "cannot read buffer");
|
||||||
|
|
||||||
|
write(STDOUT_FILENO, buf, l);
|
||||||
|
stamp.scr_len -= l;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
errx(1, "invalid direction");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
exit(0);
|
||||||
|
}
|
100
examples/script.txt
Normal file
100
examples/script.txt
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
SCRIPT(1) Cosmopolitan General Commands Manual SCRIPT(1)
|
||||||
|
|
||||||
|
𝐍𝐀𝐌𝐄
|
||||||
|
𝘀𝗰𝗿𝗶𝗽𝘁 — make typescript of terminal session
|
||||||
|
|
||||||
|
𝐒𝐘𝐍𝐎𝐏𝐒𝐈𝐒
|
||||||
|
𝘀𝗰𝗿𝗶𝗽𝘁 [-𝗮𝗱𝗲𝗳𝗸𝗽𝗾𝗿] [-𝐅 p̲i̲p̲e̲] [-𝘁 t̲i̲m̲e̲] [f̲i̲l̲e̲ [c̲o̲m̲m̲a̲n̲d̲ .̲.̲.̲]]
|
||||||
|
|
||||||
|
𝐃𝐄𝐒𝐂𝐑𝐈𝐏𝐓𝐈𝐎𝐍
|
||||||
|
The 𝘀𝗰𝗿𝗶𝗽𝘁 utility makes a typescript of everything printed on your termi‐
|
||||||
|
nal. It is useful for students who need a hardcopy record of an interac‐
|
||||||
|
tive session as proof of an assignment, as the typescript file can be
|
||||||
|
printed out later with lpr(1).
|
||||||
|
|
||||||
|
If the argument f̲i̲l̲e̲ is given, 𝘀𝗰𝗿𝗶𝗽𝘁 saves all dialogue in f̲i̲l̲e̲. If no
|
||||||
|
file name is given, the typescript is saved in the file t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲.
|
||||||
|
|
||||||
|
If the argument c̲o̲m̲m̲a̲n̲d̲ is given, 𝘀𝗰𝗿𝗶𝗽𝘁 will run the specified command
|
||||||
|
with an optional argument vector instead of an interactive shell.
|
||||||
|
|
||||||
|
The following options are available:
|
||||||
|
|
||||||
|
-𝗮 Append the output to f̲i̲l̲e̲ or t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲, retaining the prior con‐
|
||||||
|
tents.
|
||||||
|
|
||||||
|
-𝗱 When playing back a session with the -𝗽 flag, do not sleep between
|
||||||
|
records when playing back a timestamped session.
|
||||||
|
|
||||||
|
-𝗲 Accepted for compatibility with u̲t̲i̲l̲-̲l̲i̲n̲u̲x̲ 𝘀𝗰𝗿𝗶𝗽𝘁. The child com‐
|
||||||
|
mand exit status is always the exit status of 𝘀𝗰𝗿𝗶𝗽𝘁.
|
||||||
|
|
||||||
|
-𝐅 p̲i̲p̲e̲
|
||||||
|
Immediately flush output after each write. This will allow a user
|
||||||
|
to create a named pipe using mkfifo(1) and another user may watch
|
||||||
|
the live session using a utility like cat(1).
|
||||||
|
|
||||||
|
-𝗸 Log keys sent to the program as well as output.
|
||||||
|
|
||||||
|
-𝗽 Play back a session recorded with the -𝗿 flag in real time.
|
||||||
|
|
||||||
|
-𝗾 Run in quiet mode, omit the start, stop and command status mes‐
|
||||||
|
sages.
|
||||||
|
|
||||||
|
-𝗿 Record a session with input, output, and timestamping.
|
||||||
|
|
||||||
|
-𝘁 t̲i̲m̲e̲
|
||||||
|
Specify the interval at which the script output file will be
|
||||||
|
flushed to disk, in seconds. A value of 0 causes 𝘀𝗰𝗿𝗶𝗽𝘁 to flush
|
||||||
|
after every character I/O event. The default interval is 30 sec‐
|
||||||
|
onds.
|
||||||
|
|
||||||
|
The script ends when the forked shell (or command) exits (a c̲o̲n̲t̲r̲o̲l̲-̲D̲ to
|
||||||
|
exit the Bourne shell (sh(1)), and e̲x̲i̲t̲, l̲o̲g̲o̲u̲t̲ or c̲o̲n̲t̲r̲o̲l̲-̲D̲ (if i̲g̲n̲o̲r̲e̲e̲o̲f̲
|
||||||
|
is not set) for the C-shell, csh(1)).
|
||||||
|
|
||||||
|
Certain interactive commands, such as vi(1), create garbage in the type‐
|
||||||
|
script file. The 𝘀𝗰𝗿𝗶𝗽𝘁 utility works best with commands that do not ma‐
|
||||||
|
nipulate the screen. The results are meant to emulate a hardcopy terminal,
|
||||||
|
not an addressable one.
|
||||||
|
|
||||||
|
𝐄𝐍𝐕𝐈𝐑𝐎𝐍𝐌𝐄𝐍𝐓
|
||||||
|
The following environment variables are utilized by 𝘀𝗰𝗿𝗶𝗽𝘁:
|
||||||
|
|
||||||
|
SCRIPT
|
||||||
|
The SCRIPT environment variable is added to the sub-shell. If
|
||||||
|
SCRIPT already existed in the users environment, its value is over‐
|
||||||
|
written within the sub-shell. The value of SCRIPT is the name of
|
||||||
|
the t̲y̲p̲e̲s̲c̲r̲i̲p̲t̲ file.
|
||||||
|
|
||||||
|
SHELL If the variable SHELL exists, the shell forked by 𝘀𝗰𝗿𝗶𝗽𝘁 will be
|
||||||
|
that shell. If SHELL is not set, the Bourne shell is assumed.
|
||||||
|
(Most shells set this variable automatically).
|
||||||
|
|
||||||
|
𝐒𝐄𝐄 𝐀𝐋𝐒𝐎
|
||||||
|
csh(1) (for the h̲i̲s̲t̲o̲r̲y̲ mechanism)
|
||||||
|
|
||||||
|
𝐇𝐈𝐒𝐓𝐎𝐑𝐘
|
||||||
|
The 𝘀𝗰𝗿𝗶𝗽𝘁 command appeared in 3.0BSD.
|
||||||
|
|
||||||
|
The -𝗱, -𝗽 and -𝗿 options first appeared in NetBSD 2.0 and were ported to
|
||||||
|
FreeBSD 9.2.
|
||||||
|
|
||||||
|
𝐁𝐔𝐆𝐒
|
||||||
|
The 𝘀𝗰𝗿𝗶𝗽𝘁 utility places 𝗲𝘃𝗲𝗿𝘆𝘁𝗵𝗶𝗻𝗴 in the log file, including linefeeds
|
||||||
|
and backspaces. This is not what the naive user expects.
|
||||||
|
|
||||||
|
It is not possible to specify a command without also naming the script file
|
||||||
|
because of argument parsing compatibility issues.
|
||||||
|
|
||||||
|
When running in -𝗸 mode, echo cancelling is far from ideal. The slave ter‐
|
||||||
|
minal mode is checked for ECHO mode to check when to avoid manual echo log‐
|
||||||
|
ging. This does not work when the terminal is in a raw mode where the pro‐
|
||||||
|
gram being run is doing manual echo.
|
||||||
|
|
||||||
|
If 𝘀𝗰𝗿𝗶𝗽𝘁 reads zero bytes from the terminal, it switches to a mode when it
|
||||||
|
only attempts to read once a second until there is data to read. This pre‐
|
||||||
|
vents 𝘀𝗰𝗿𝗶𝗽𝘁 from spinning on zero-byte reads, but might cause a 1-second
|
||||||
|
delay in processing of user input.
|
||||||
|
|
||||||
|
BSD September 1, 2020 BSD
|
617
examples/whois.c
Normal file
617
examples/whois.c
Normal file
|
@ -0,0 +1,617 @@
|
||||||
|
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||||
|
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
|
│ Copyright (c) 1980, 1993 │
|
||||||
|
│ The Regents of the University of California. All rights reserved. │
|
||||||
|
│ │
|
||||||
|
│ Redistribution and use in source and binary forms, with or without │
|
||||||
|
│ modification, are permitted provided that the following conditions │
|
||||||
|
│ are met: │
|
||||||
|
│ 1. Redistributions of source code must retain the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer. │
|
||||||
|
│ 2. Redistributions in binary form must reproduce the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer in the │
|
||||||
|
│ documentation and/or other materials provided with the distribution. │
|
||||||
|
│ 3. Neither the name of the University nor the names of its contributors │
|
||||||
|
│ may be used to endorse or promote products derived from this software │
|
||||||
|
│ without specific prior written permission. │
|
||||||
|
│ │
|
||||||
|
│ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND │
|
||||||
|
│ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE │
|
||||||
|
│ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE │
|
||||||
|
│ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE │
|
||||||
|
│ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL │
|
||||||
|
│ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS │
|
||||||
|
│ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) │
|
||||||
|
│ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT │
|
||||||
|
│ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY │
|
||||||
|
│ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF │
|
||||||
|
│ SUCH DAMAGE. │
|
||||||
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/dns/dns.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/log/bsd.h"
|
||||||
|
#include "libc/mem/fmt.h"
|
||||||
|
#include "libc/mem/mem.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/sock/struct/pollfd.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
#include "libc/sysv/consts/af.h"
|
||||||
|
#include "libc/sysv/consts/ex.h"
|
||||||
|
#include "libc/sysv/consts/f.h"
|
||||||
|
#include "libc/sysv/consts/o.h"
|
||||||
|
#include "libc/sysv/consts/poll.h"
|
||||||
|
#include "libc/sysv/consts/sock.h"
|
||||||
|
#include "third_party/getopt/getopt.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
asm(".ident\t\"\\n\\n\
|
||||||
|
FreeBSD Whois (BSD-3 License)\\n\
|
||||||
|
Copyright (c) 1980, 1993\\n\
|
||||||
|
\tThe Regents of the University of California.\\n\
|
||||||
|
\tAll rights reserved.\"");
|
||||||
|
asm(".include \"libc/disclaimer.inc\"");
|
||||||
|
|
||||||
|
#define ABUSEHOST "whois.abuse.net"
|
||||||
|
#define ANICHOST "whois.arin.net"
|
||||||
|
#define DENICHOST "whois.denic.de"
|
||||||
|
#define DKNICHOST "whois.dk-hostmaster.dk"
|
||||||
|
#define FNICHOST "whois.afrinic.net"
|
||||||
|
#define GNICHOST "whois.nic.gov"
|
||||||
|
#define IANAHOST "whois.iana.org"
|
||||||
|
#define INICHOST "whois.internic.net"
|
||||||
|
#define KNICHOST "whois.krnic.net"
|
||||||
|
#define LNICHOST "whois.lacnic.net"
|
||||||
|
#define MNICHOST "whois.ra.net"
|
||||||
|
#define PDBHOST "whois.peeringdb.com"
|
||||||
|
#define PNICHOST "whois.apnic.net"
|
||||||
|
#define QNICHOST_TAIL ".whois-servers.net"
|
||||||
|
#define RNICHOST "whois.ripe.net"
|
||||||
|
#define VNICHOST "whois.verisign-grs.com"
|
||||||
|
|
||||||
|
#define DEFAULT_PORT "whois"
|
||||||
|
|
||||||
|
#define WHOIS_RECURSE 0x01
|
||||||
|
#define WHOIS_QUICK 0x02
|
||||||
|
#define WHOIS_SPAM_ME 0x04
|
||||||
|
|
||||||
|
#define CHOPSPAM ">>> Last update of WHOIS database:"
|
||||||
|
|
||||||
|
#define ishost(h) (isalnum((unsigned char)h) || h == '.' || h == '-')
|
||||||
|
|
||||||
|
#define SCAN(p, end, check) \
|
||||||
|
while ((p) < (end)) \
|
||||||
|
if (check) ++(p); \
|
||||||
|
else break
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
const char *suffix, *server;
|
||||||
|
} whoiswhere[] = {
|
||||||
|
/* Various handles */
|
||||||
|
{ "-ARIN", ANICHOST },
|
||||||
|
{ "-NICAT", "at" QNICHOST_TAIL },
|
||||||
|
{ "-NORID", "no" QNICHOST_TAIL },
|
||||||
|
{ "-RIPE", RNICHOST },
|
||||||
|
/* Nominet's whois server doesn't return referrals to JANET */
|
||||||
|
{ ".ac.uk", "ac.uk" QNICHOST_TAIL },
|
||||||
|
{ ".gov.uk", "ac.uk" QNICHOST_TAIL },
|
||||||
|
{ "", IANAHOST }, /* default */
|
||||||
|
{ NULL, NULL } /* safety belt */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define WHOIS_REFERRAL(s) { s, sizeof(s) - 1 }
|
||||||
|
static struct {
|
||||||
|
const char *prefix;
|
||||||
|
size_t len;
|
||||||
|
} whois_referral[] = {
|
||||||
|
WHOIS_REFERRAL("whois:"), /* IANA */
|
||||||
|
WHOIS_REFERRAL("Whois Server:"),
|
||||||
|
WHOIS_REFERRAL("Registrar WHOIS Server:"), /* corporatedomains.com */
|
||||||
|
WHOIS_REFERRAL("ReferralServer: whois://"), /* ARIN */
|
||||||
|
WHOIS_REFERRAL("ReferralServer: rwhois://"), /* ARIN */
|
||||||
|
WHOIS_REFERRAL("descr: region. Please query"), /* AfriNIC */
|
||||||
|
{ NULL, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We have a list of patterns for RIRs that assert ignorance rather than
|
||||||
|
* providing referrals. If that happens, we guess that ARIN will be more
|
||||||
|
* helpful. But, before following a referral to an RIR, we check if we have
|
||||||
|
* asked that RIR already, and if so we make another guess.
|
||||||
|
*/
|
||||||
|
static const char *actually_arin[] = {
|
||||||
|
"netname: ERX-NETBLOCK\n", /* APNIC */
|
||||||
|
"netname: NON-RIPE-NCC-MANAGED-ADDRESS-BLOCK\n",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int loop;
|
||||||
|
const char *host;
|
||||||
|
} try_rir[] = {
|
||||||
|
{ 0, ANICHOST },
|
||||||
|
{ 0, RNICHOST },
|
||||||
|
{ 0, PNICHOST },
|
||||||
|
{ 0, FNICHOST },
|
||||||
|
{ 0, LNICHOST },
|
||||||
|
{ 0, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_rir(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; try_rir[i].host != NULL; i++)
|
||||||
|
try_rir[i].loop = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *port = DEFAULT_PORT;
|
||||||
|
|
||||||
|
static const char *choose_server(char *);
|
||||||
|
static struct addrinfo *gethostinfo(const char *, const char *, int);
|
||||||
|
static void s_asprintf(char **ret, const char *format, ...);
|
||||||
|
static void usage(void);
|
||||||
|
static void whois(const char *, const char *, const char *, int);
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
const char *country, *host;
|
||||||
|
int ch, flags;
|
||||||
|
|
||||||
|
#ifdef SOCKS
|
||||||
|
SOCKSinit(argv[0]);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
country = host = NULL;
|
||||||
|
flags = 0;
|
||||||
|
while ((ch = getopt(argc, argv, "aAbc:fgh:iIklmp:PQrRS")) != -1) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'a':
|
||||||
|
host = ANICHOST;
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
host = PNICHOST;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
host = ABUSEHOST;
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
country = optarg;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
host = FNICHOST;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
host = GNICHOST;
|
||||||
|
break;
|
||||||
|
case 'h':
|
||||||
|
host = optarg;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
host = INICHOST;
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
host = IANAHOST;
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
host = KNICHOST;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
host = LNICHOST;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
host = MNICHOST;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
port = optarg;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
host = PDBHOST;
|
||||||
|
break;
|
||||||
|
case 'Q':
|
||||||
|
flags |= WHOIS_QUICK;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
host = RNICHOST;
|
||||||
|
break;
|
||||||
|
case 'R':
|
||||||
|
flags |= WHOIS_RECURSE;
|
||||||
|
break;
|
||||||
|
case 'S':
|
||||||
|
flags |= WHOIS_SPAM_ME;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
default:
|
||||||
|
usage();
|
||||||
|
/* NOTREACHED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
argc -= optind;
|
||||||
|
argv += optind;
|
||||||
|
|
||||||
|
if (!argc || (country != NULL && host != NULL))
|
||||||
|
usage();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If no host or country is specified, rely on referrals from IANA.
|
||||||
|
*/
|
||||||
|
if (host == NULL && country == NULL) {
|
||||||
|
if ((host = getenv("WHOIS_SERVER")) == NULL &&
|
||||||
|
(host = getenv("RA_SERVER")) == NULL) {
|
||||||
|
if (!(flags & WHOIS_QUICK))
|
||||||
|
flags |= WHOIS_RECURSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (argc-- > 0) {
|
||||||
|
if (country != NULL) {
|
||||||
|
char *qnichost;
|
||||||
|
s_asprintf(&qnichost, "%s%s", country, QNICHOST_TAIL);
|
||||||
|
whois(*argv, qnichost, port, flags);
|
||||||
|
free(qnichost);
|
||||||
|
} else
|
||||||
|
whois(*argv, host != NULL ? host :
|
||||||
|
choose_server(*argv), port, flags);
|
||||||
|
reset_rir();
|
||||||
|
argv++;
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
choose_server(char *domain)
|
||||||
|
{
|
||||||
|
size_t len = strlen(domain);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; whoiswhere[i].suffix != NULL; i++) {
|
||||||
|
size_t suffix_len = strlen(whoiswhere[i].suffix);
|
||||||
|
if (len > suffix_len &&
|
||||||
|
strcasecmp(domain + len - suffix_len,
|
||||||
|
whoiswhere[i].suffix) == 0)
|
||||||
|
return (whoiswhere[i].server);
|
||||||
|
}
|
||||||
|
errx(EX_SOFTWARE, "no default whois server");
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct addrinfo *
|
||||||
|
gethostinfo(const char *host, const char *hport, int exit_on_noname)
|
||||||
|
{
|
||||||
|
struct addrinfo hints, *res;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
memset(&hints, 0, sizeof(hints));
|
||||||
|
hints.ai_flags = AI_CANONNAME;
|
||||||
|
hints.ai_family = AF_UNSPEC;
|
||||||
|
hints.ai_socktype = SOCK_STREAM;
|
||||||
|
res = NULL;
|
||||||
|
error = getaddrinfo(host, hport, &hints, &res);
|
||||||
|
if (error && (exit_on_noname || error != EAI_NONAME))
|
||||||
|
err(EX_NOHOST, "%s: %s", host, gai_strerror(error));
|
||||||
|
return (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper for asprintf(3) that exits on error.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
s_asprintf(char **ret, const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
if (vasprintf(ret, format, ap) == -1) {
|
||||||
|
va_end(ap);
|
||||||
|
err(EX_OSERR, "vasprintf()");
|
||||||
|
}
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
connect_to_any_host(struct addrinfo *hostres)
|
||||||
|
{
|
||||||
|
struct addrinfo *res;
|
||||||
|
nfds_t i, j;
|
||||||
|
size_t count;
|
||||||
|
struct pollfd *fds;
|
||||||
|
int timeout = 180, s = -1;
|
||||||
|
|
||||||
|
for (res = hostres, count = 0; res; res = res->ai_next)
|
||||||
|
count++;
|
||||||
|
fds = calloc(count, sizeof(*fds));
|
||||||
|
if (fds == NULL)
|
||||||
|
err(EX_OSERR, "calloc()");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Traverse the result list elements and make non-block
|
||||||
|
* connection attempts.
|
||||||
|
*/
|
||||||
|
count = i = 0;
|
||||||
|
for (res = hostres; res != NULL; res = res->ai_next) {
|
||||||
|
s = socket(res->ai_family, res->ai_socktype | SOCK_NONBLOCK,
|
||||||
|
res->ai_protocol);
|
||||||
|
if (s < 0)
|
||||||
|
continue;
|
||||||
|
if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
|
||||||
|
if (errno == EINPROGRESS) {
|
||||||
|
/* Add the socket to poll list */
|
||||||
|
fds[i].fd = s;
|
||||||
|
fds[i].events = POLLERR | POLLHUP |
|
||||||
|
POLLIN | POLLOUT;
|
||||||
|
/*
|
||||||
|
* From here until a socket connects, the
|
||||||
|
* socket fd is owned by the fds[] poll array.
|
||||||
|
*/
|
||||||
|
s = -1;
|
||||||
|
count++;
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
close(s);
|
||||||
|
s = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poll only if we have something to poll,
|
||||||
|
* otherwise just go ahead and try next
|
||||||
|
* address
|
||||||
|
*/
|
||||||
|
if (count == 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we are at the last address, poll until a connection is
|
||||||
|
* established or we failed all connection attempts.
|
||||||
|
*/
|
||||||
|
if (res->ai_next == NULL)
|
||||||
|
timeout = INFTIM;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Poll the watched descriptors for successful connections:
|
||||||
|
* if we still have more untried resolved addresses, poll only
|
||||||
|
* once; otherwise, poll until all descriptors have errors,
|
||||||
|
* which will be considered as ETIMEDOUT later.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = poll(fds, i, timeout);
|
||||||
|
if (n == 0) {
|
||||||
|
/*
|
||||||
|
* No event reported in time. Try with a
|
||||||
|
* smaller timeout (but cap at 2-3ms)
|
||||||
|
* after a new host have been added.
|
||||||
|
*/
|
||||||
|
if (timeout >= 3)
|
||||||
|
timeout >>= 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
} else if (n < 0) {
|
||||||
|
/*
|
||||||
|
* errno here can only be EINTR which we would
|
||||||
|
* want to clean up and bail out.
|
||||||
|
*/
|
||||||
|
s = -1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for the event(s) we have seen.
|
||||||
|
*/
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if (fds[j].fd == -1 || fds[j].events == 0 ||
|
||||||
|
fds[j].revents == 0)
|
||||||
|
continue;
|
||||||
|
if (fds[j].revents & ~(POLLIN | POLLOUT)) {
|
||||||
|
close(fds[j].fd);
|
||||||
|
fds[j].fd = -1;
|
||||||
|
fds[j].events = 0;
|
||||||
|
count--;
|
||||||
|
continue;
|
||||||
|
} else if (fds[j].revents & (POLLIN | POLLOUT)) {
|
||||||
|
/* Connect succeeded. */
|
||||||
|
s = fds[j].fd;
|
||||||
|
fds[j].fd = -1;
|
||||||
|
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} while (timeout == INFTIM && count != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* All attempts were failed */
|
||||||
|
s = -1;
|
||||||
|
if (count == 0)
|
||||||
|
errno = ETIMEDOUT;
|
||||||
|
|
||||||
|
done:
|
||||||
|
/* Close all watched fds except the succeeded one */
|
||||||
|
for (j = 0; j < i; j++)
|
||||||
|
if (fds[j].fd != -1)
|
||||||
|
close(fds[j].fd);
|
||||||
|
free(fds);
|
||||||
|
return (s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
whois(const char *query, const char *hostname, const char *hostport, int flags)
|
||||||
|
{
|
||||||
|
FILE *fp;
|
||||||
|
struct addrinfo *hostres;
|
||||||
|
char *buf, *host, *nhost, *nport, *p;
|
||||||
|
int comment, s, f;
|
||||||
|
size_t len, i;
|
||||||
|
|
||||||
|
hostres = gethostinfo(hostname, hostport, 1);
|
||||||
|
s = connect_to_any_host(hostres);
|
||||||
|
if (s == -1)
|
||||||
|
err(EX_OSERR, "connect()");
|
||||||
|
|
||||||
|
/* Restore default blocking behavior. */
|
||||||
|
if ((f = fcntl(s, F_GETFL)) == -1)
|
||||||
|
err(EX_OSERR, "fcntl()");
|
||||||
|
f &= ~O_NONBLOCK;
|
||||||
|
if (fcntl(s, F_SETFL, f) == -1)
|
||||||
|
err(EX_OSERR, "fcntl()");
|
||||||
|
|
||||||
|
fp = fdopen(s, "r+");
|
||||||
|
if (fp == NULL)
|
||||||
|
err(EX_OSERR, "fdopen()");
|
||||||
|
|
||||||
|
if (!(flags & WHOIS_SPAM_ME) &&
|
||||||
|
(strcasecmp(hostname, DENICHOST) == 0 ||
|
||||||
|
strcasecmp(hostname, "de" QNICHOST_TAIL) == 0)) {
|
||||||
|
const char *q;
|
||||||
|
int idn = 0;
|
||||||
|
for (q = query; *q != '\0'; q++)
|
||||||
|
if (!isascii(*q))
|
||||||
|
idn = 1;
|
||||||
|
fprintf(fp, "-T dn%s %s\r\n", idn ? "" : ",ace", query);
|
||||||
|
} else if (!(flags & WHOIS_SPAM_ME) &&
|
||||||
|
(strcasecmp(hostname, DKNICHOST) == 0 ||
|
||||||
|
strcasecmp(hostname, "dk" QNICHOST_TAIL) == 0))
|
||||||
|
fprintf(fp, "--show-handles %s\r\n", query);
|
||||||
|
else if ((flags & WHOIS_SPAM_ME) ||
|
||||||
|
strchr(query, ' ') != NULL)
|
||||||
|
fprintf(fp, "%s\r\n", query);
|
||||||
|
else if (strcasecmp(hostname, ANICHOST) == 0) {
|
||||||
|
if (strncasecmp(query, "AS", 2) == 0 &&
|
||||||
|
strspn(query+2, "0123456789") == strlen(query+2))
|
||||||
|
fprintf(fp, "+ a %s\r\n", query+2);
|
||||||
|
else
|
||||||
|
fprintf(fp, "+ %s\r\n", query);
|
||||||
|
} else if (strcasecmp(hostres->ai_canonname, VNICHOST) == 0)
|
||||||
|
fprintf(fp, "domain %s\r\n", query);
|
||||||
|
else
|
||||||
|
fprintf(fp, "%s\r\n", query);
|
||||||
|
fflush(fp);
|
||||||
|
|
||||||
|
comment = 0;
|
||||||
|
if (!(flags & WHOIS_SPAM_ME) &&
|
||||||
|
(strcasecmp(hostname, ANICHOST) == 0 ||
|
||||||
|
strcasecmp(hostname, RNICHOST) == 0)) {
|
||||||
|
comment = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
nhost = NULL;
|
||||||
|
while ((buf = fgetln(fp, &len)) != NULL) {
|
||||||
|
/* Nominet */
|
||||||
|
if (!(flags & WHOIS_SPAM_ME) &&
|
||||||
|
len == 5 && strncmp(buf, "-- \r\n", 5) == 0)
|
||||||
|
break;
|
||||||
|
/* RIRs */
|
||||||
|
if (comment == 1 && buf[0] == '#')
|
||||||
|
break;
|
||||||
|
else if (comment == 2) {
|
||||||
|
if (strchr("#%\r\n", buf[0]) != NULL)
|
||||||
|
continue;
|
||||||
|
else
|
||||||
|
comment = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%.*s", (int)len, buf);
|
||||||
|
|
||||||
|
if ((flags & WHOIS_RECURSE) && nhost == NULL) {
|
||||||
|
for (i = 0; whois_referral[i].prefix != NULL; i++) {
|
||||||
|
p = buf;
|
||||||
|
SCAN(p, buf+len, *p == ' ');
|
||||||
|
if (strncasecmp(p, whois_referral[i].prefix,
|
||||||
|
whois_referral[i].len) != 0)
|
||||||
|
continue;
|
||||||
|
p += whois_referral[i].len;
|
||||||
|
SCAN(p, buf+len, *p == ' ');
|
||||||
|
host = p;
|
||||||
|
SCAN(p, buf+len, ishost(*p));
|
||||||
|
if (p > host) {
|
||||||
|
char *pstr;
|
||||||
|
|
||||||
|
s_asprintf(&nhost, "%.*s",
|
||||||
|
(int)(p - host), host);
|
||||||
|
|
||||||
|
if (*p != ':') {
|
||||||
|
s_asprintf(&nport, "%s", port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
pstr = ++p;
|
||||||
|
SCAN(p, buf+len, isdigit(*p));
|
||||||
|
if (p > pstr && (p - pstr) < 6) {
|
||||||
|
s_asprintf(&nport, "%.*s",
|
||||||
|
(int)(p - pstr), pstr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Invalid port; don't recurse */
|
||||||
|
free(nhost);
|
||||||
|
nhost = NULL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (i = 0; actually_arin[i] != NULL; i++) {
|
||||||
|
if (strncmp(buf, actually_arin[i], len) == 0) {
|
||||||
|
s_asprintf(&nhost, "%s", ANICHOST);
|
||||||
|
s_asprintf(&nport, "%s", port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Verisign etc. */
|
||||||
|
if (!(flags & WHOIS_SPAM_ME) &&
|
||||||
|
len >= sizeof(CHOPSPAM)-1 &&
|
||||||
|
(strncasecmp(buf, CHOPSPAM, sizeof(CHOPSPAM)-1) == 0 ||
|
||||||
|
strncasecmp(buf, CHOPSPAM+4, sizeof(CHOPSPAM)-5) == 0)) {
|
||||||
|
printf("\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
freeaddrinfo(hostres);
|
||||||
|
|
||||||
|
f = 0;
|
||||||
|
for (i = 0; try_rir[i].host != NULL; i++) {
|
||||||
|
/* Remember visits to RIRs */
|
||||||
|
if (try_rir[i].loop == 0 &&
|
||||||
|
strcasecmp(try_rir[i].host, hostname) == 0)
|
||||||
|
try_rir[i].loop = 1;
|
||||||
|
/* Do we need to find an alternative RIR? */
|
||||||
|
if (try_rir[i].loop != 0 && nhost != NULL &&
|
||||||
|
strcasecmp(try_rir[i].host, nhost) == 0) {
|
||||||
|
free(nhost);
|
||||||
|
nhost = NULL;
|
||||||
|
free(nport);
|
||||||
|
nport = NULL;
|
||||||
|
f = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (f) {
|
||||||
|
/* Find a replacement RIR */
|
||||||
|
for (i = 0; try_rir[i].host != NULL; i++) {
|
||||||
|
if (try_rir[i].loop == 0) {
|
||||||
|
s_asprintf(&nhost, "%s", try_rir[i].host);
|
||||||
|
s_asprintf(&nport, "%s", port);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nhost != NULL) {
|
||||||
|
/* Ignore self-referrals */
|
||||||
|
if (strcasecmp(hostname, nhost) != 0) {
|
||||||
|
printf("# %s\n\n", nhost);
|
||||||
|
whois(query, nhost, nport, flags);
|
||||||
|
}
|
||||||
|
free(nhost);
|
||||||
|
free(nport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr,
|
||||||
|
"usage: whois [-aAbfgiIklmPQrRS] [-c country-code | -h hostname] "
|
||||||
|
"[-p port] name ...\n");
|
||||||
|
exit(EX_USAGE);
|
||||||
|
}
|
|
@ -16,6 +16,27 @@
|
||||||
│ 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/calls/calls.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
int grantpt(int fd) { return 0; }
|
/**
|
||||||
|
* Grants access to subordinate pseudoteletypewriter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or -1 w/ errno
|
||||||
|
* @raise EBADF if fd isn't open
|
||||||
|
* @raise EINVAL if fd is valid but not associated with pty
|
||||||
|
* @raise EACCES if pseudoterminal couldn't be accessed
|
||||||
|
*/
|
||||||
|
int grantpt(int fd) {
|
||||||
|
int rc;
|
||||||
|
if (IsXnu()) {
|
||||||
|
rc = sys_ioctl(fd, TIOCPTYGRANT);
|
||||||
|
} else {
|
||||||
|
rc = _isptmaster(fd);
|
||||||
|
}
|
||||||
|
STRACE("grantpt(%d) → %d% m", fd, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
|
@ -12,13 +12,6 @@ COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
#define kIoMotion ((const int8_t[3]){1, 0, 0})
|
#define kIoMotion ((const int8_t[3]){1, 0, 0})
|
||||||
|
|
||||||
struct IoctlPtmGet {
|
|
||||||
int theduxfd;
|
|
||||||
int workerfd;
|
|
||||||
char theduxname[16];
|
|
||||||
char workername[16];
|
|
||||||
};
|
|
||||||
|
|
||||||
hidden extern struct Fds g_fds;
|
hidden extern struct Fds g_fds;
|
||||||
hidden extern const struct Fd kEmptyFd;
|
hidden extern const struct Fd kEmptyFd;
|
||||||
|
|
||||||
|
|
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2022 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,11 +16,23 @@
|
||||||
│ 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/log/bsd.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
|
||||||
wontreturn void(errx)(int eval, const char *fmt, ...) {
|
int _isptmaster(int fd) {
|
||||||
va_list va;
|
if (IsFreebsd()) {
|
||||||
va_start(va, fmt);
|
if (!sys_ioctl(fd, TIOCPTMASTER)) {
|
||||||
(verrx)(eval, fmt, va);
|
return 0;
|
||||||
va_end(va);
|
} else {
|
||||||
|
if (errno != EBADF) {
|
||||||
|
errno = EINVAL;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -18,12 +18,23 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/calls/ioctl.h"
|
#include "libc/calls/ioctl.h"
|
||||||
|
#include "libc/calls/struct/termios.h"
|
||||||
|
#include "libc/calls/struct/winsize.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/kprintf.h"
|
||||||
|
#include "libc/log/rop.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/pty.h"
|
#include "libc/sysv/consts/pty.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
|
||||||
|
struct IoctlPtmGet {
|
||||||
|
int m;
|
||||||
|
int s;
|
||||||
|
char mname[16];
|
||||||
|
char sname[16];
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens new pseudo teletypewriter.
|
* Opens new pseudo teletypewriter.
|
||||||
|
@ -37,24 +48,29 @@
|
||||||
*/
|
*/
|
||||||
int openpty(int *mfd, int *sfd, char *name, const struct termios *tio,
|
int openpty(int *mfd, int *sfd, char *name, const struct termios *tio,
|
||||||
const struct winsize *wsz) {
|
const struct winsize *wsz) {
|
||||||
int m, s, n;
|
int m, s, p;
|
||||||
char buf[20];
|
const char *t;
|
||||||
if ((m = open("/dev/ptmx", O_RDWR | O_NOCTTY)) != -1) {
|
struct IoctlPtmGet ptm;
|
||||||
n = 0;
|
RETURN_ON_ERROR((m = posix_openpt(O_RDWR | O_NOCTTY)));
|
||||||
if (!ioctl(m, TIOCSPTLCK, &n) && !ioctl(m, TIOCGPTN, &n)) {
|
if (!IsOpenbsd()) {
|
||||||
if (!name) name = buf;
|
RETURN_ON_ERROR(grantpt(m));
|
||||||
name[0] = '/', name[1] = 'd', name[2] = 'e', name[3] = 'v';
|
RETURN_ON_ERROR(unlockpt(m));
|
||||||
name[4] = '/', name[5] = 'p', name[6] = 't', name[7] = 's';
|
if (!(t = ptsname(m))) goto OnError;
|
||||||
name[8] = '/', FormatInt32(name + 9, n);
|
RETURN_ON_ERROR((s = open(t, O_RDWR)));
|
||||||
if ((s = open(name, O_RDWR | O_NOCTTY)) != -1) {
|
} else {
|
||||||
if (tio) ioctl(s, TCSETS, tio);
|
RETURN_ON_ERROR(ioctl(m, PTMGET, &ptm));
|
||||||
if (wsz) ioctl(s, TIOCSWINSZ, wsz);
|
close(m);
|
||||||
|
m = ptm.m;
|
||||||
|
s = ptm.s;
|
||||||
|
t = ptm.sname;
|
||||||
|
}
|
||||||
*mfd = m;
|
*mfd = m;
|
||||||
*sfd = s;
|
*sfd = s;
|
||||||
|
if (name) strcpy(name, t);
|
||||||
|
if (tio) ioctl(s, TCSETSF, tio);
|
||||||
|
if (wsz) ioctl(s, TIOCSWINSZ, wsz);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
OnError:
|
||||||
}
|
if (m != -1) close(m);
|
||||||
close(m);
|
|
||||||
}
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,43 +16,35 @@
|
||||||
│ 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/calls/calls.h"
|
|
||||||
#include "libc/calls/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"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/sysv/consts/o.h"
|
#include "libc/sysv/consts/o.h"
|
||||||
#include "libc/sysv/consts/pty.h"
|
|
||||||
#include "libc/sysv/consts/termios.h"
|
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens new pseudo teletypewriter.
|
* Opens new pseudo teletypewriter.
|
||||||
*
|
*
|
||||||
|
* @return fd of master pty, or -1 w/ errno
|
||||||
* @params flags is usually O_RDWR|O_NOCTTY
|
* @params flags is usually O_RDWR|O_NOCTTY
|
||||||
* @return file descriptor, or -1 w/ errno
|
* @return file descriptor, or -1 w/ errno
|
||||||
*/
|
*/
|
||||||
int posix_openpt(int flags) {
|
int posix_openpt(int flags) {
|
||||||
int fd, ilduce;
|
int rc;
|
||||||
struct IoctlPtmGet ptm;
|
if ((flags & O_ACCMODE) != O_RDWR) {
|
||||||
if ((flags & O_ACCMODE) != O_RDWR) return einval();
|
rc = einval();
|
||||||
if (SupportsFreebsd() &&
|
} else if (IsLinux() || IsXnu()) {
|
||||||
((fd = sys_posix_openpt(flags)) != -1 || errno != ENOSYS)) {
|
rc = sys_open("/dev/ptmx", flags, 0);
|
||||||
return fd;
|
} else if (IsOpenbsd()) {
|
||||||
} else if ((fd = open("/dev/ptmx", flags)) != -1 || errno != ENOENT) {
|
rc = sys_open("/dev/ptm", flags, 0);
|
||||||
return fd;
|
} else if (IsFreebsd()) {
|
||||||
} else if (SupportsOpenbsd() &&
|
rc = sys_posix_openpt(flags);
|
||||||
((fd = open("/dev/ptm", flags)) != -1 || errno != ENOENT)) {
|
if (rc == -1 && errno == ENOSPC) errno = EAGAIN;
|
||||||
if (ioctl(fd, PTMGET, &ptm) != -1) {
|
|
||||||
close(ptm.workerfd);
|
|
||||||
ilduce = ptm.theduxfd;
|
|
||||||
} else {
|
} else {
|
||||||
ilduce = -1;
|
rc = enosys();
|
||||||
}
|
|
||||||
close(fd);
|
|
||||||
return ilduce;
|
|
||||||
} else {
|
|
||||||
return enosys();
|
|
||||||
}
|
}
|
||||||
|
STRACE("posix_openpt(%#o) → %d% m", flags, rc);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,25 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/errno.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
|
|
||||||
static char g_ptsname[32];
|
static char g_ptsname[256];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets name subordinate pseudoteletypewriter.
|
||||||
|
*
|
||||||
|
* @return static string path on success, or NULL w/ errno
|
||||||
|
*/
|
||||||
char *ptsname(int fd) {
|
char *ptsname(int fd) {
|
||||||
return ptsname_r(fd, g_ptsname, sizeof(g_ptsname)) ? g_ptsname : NULL;
|
char *res;
|
||||||
|
errno_t e;
|
||||||
|
if (!(e = ptsname_r(fd, g_ptsname, sizeof(g_ptsname)))) {
|
||||||
|
res = g_ptsname;
|
||||||
|
} else {
|
||||||
|
errno = e;
|
||||||
|
res = 0;
|
||||||
|
}
|
||||||
|
STRACE("ptsname(%d) → %s% m", fd, res);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,23 +17,69 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
#include "libc/errno.h"
|
#include "libc/errno.h"
|
||||||
#include "libc/fmt/itoa.h"
|
#include "libc/fmt/itoa.h"
|
||||||
|
#include "libc/paths.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
#include "libc/sysv/consts/termios.h"
|
#include "libc/sysv/consts/termios.h"
|
||||||
#include "libc/sysv/errfuns.h"
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
errno_t ptsname_r(int fd, char *buf, size_t size) {
|
struct fiodgname_arg {
|
||||||
|
int len;
|
||||||
|
void *buf;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int PtsName(int fd, char *buf, size_t size) {
|
||||||
|
if (size < 9 + 12) return erange();
|
||||||
|
if (_isptmaster(fd)) return -1;
|
||||||
|
|
||||||
|
if (IsLinux()) {
|
||||||
int pty;
|
int pty;
|
||||||
char tb[32];
|
if (sys_ioctl(fd, TIOCGPTN, &pty)) return -1;
|
||||||
if (size) {
|
buf[0] = '/', buf[1] = 'd', buf[2] = 'e', buf[3] = 'v';
|
||||||
if (!buf) return einval();
|
buf[4] = '/', buf[5] = 'p', buf[6] = 't', buf[7] = 's';
|
||||||
if (ioctl(fd, TIOCGPTN, &pty) == -1) return errno;
|
buf[8] = '/', FormatInt32(buf + 9, pty);
|
||||||
FormatInt32(stpcpy(tb, "/dev/pts/"), pty);
|
return 0;
|
||||||
if (strlen(tb) + 1 >= size) return (errno = ERANGE);
|
}
|
||||||
stpcpy(buf, tb);
|
|
||||||
/* TODO(jart): OpenBSD OMG */
|
if (IsFreebsd()) {
|
||||||
|
struct fiodgname_arg fgn = {size - 5, buf + 5};
|
||||||
|
buf[0] = '/', buf[1] = 'd';
|
||||||
|
buf[2] = 'e', buf[3] = 'v';
|
||||||
|
buf[4] = '/', buf[5] = 0;
|
||||||
|
if (sys_ioctl(fd, FIODGNAME, &fgn) == -1) {
|
||||||
|
if (errno == EINVAL) errno = ERANGE;
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsXnu()) {
|
||||||
|
char b2[128];
|
||||||
|
if (sys_ioctl(fd, TIOCPTYGNAME, b2)) return -1;
|
||||||
|
if (strlen(b2) + 1 > size) return erange();
|
||||||
|
strcpy(buf, b2);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return enosys();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets name subordinate pseudoteletypewriter.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or errno on error
|
||||||
|
*/
|
||||||
|
errno_t ptsname_r(int fd, char *buf, size_t size) {
|
||||||
|
int rc, e = errno;
|
||||||
|
if (!PtsName(fd, buf, size)) {
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
rc = errno;
|
||||||
|
errno = e;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ i64 sys_readlinkat(int, const char *, char *, u64) hidden;
|
||||||
i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
|
i64 sys_sendfile(i32, i32, i64 *, u64) hidden;
|
||||||
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
|
i64 sys_splice(i32, i64 *, i32, i64 *, u64, u32) hidden;
|
||||||
i64 sys_write(i32, const void *, u64) hidden;
|
i64 sys_write(i32, const void *, u64) hidden;
|
||||||
|
int _isptmaster(int);
|
||||||
u32 sys_getegid(void) hidden;
|
u32 sys_getegid(void) hidden;
|
||||||
u32 sys_geteuid(void) hidden;
|
u32 sys_geteuid(void) hidden;
|
||||||
u32 sys_getgid(void) hidden;
|
u32 sys_getgid(void) hidden;
|
||||||
|
|
|
@ -17,11 +17,32 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/calls/termios.h"
|
#include "libc/calls/termios.h"
|
||||||
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/sysv/consts/pty.h"
|
#include "libc/sysv/consts/pty.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unlocks pseudoteletypewriter pair.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or -1 w/ errno
|
||||||
|
* @raise EBADF if fd isn't open
|
||||||
|
* @raise EINVAL if fd is valid but not associated with pty
|
||||||
|
*/
|
||||||
int unlockpt(int fd) {
|
int unlockpt(int fd) {
|
||||||
|
int rc;
|
||||||
|
if (IsFreebsd() || IsOpenbsd()) {
|
||||||
|
rc = _isptmaster(fd);
|
||||||
|
} else if (IsXnu()) {
|
||||||
|
rc = sys_ioctl(fd, TIOCPTYUNLK);
|
||||||
|
} else if (IsLinux()) {
|
||||||
int unlock = 0;
|
int unlock = 0;
|
||||||
/* TODO(jart) */
|
rc = sys_ioctl(fd, TIOCSPTLCK, &unlock);
|
||||||
return ioctl(fd, TIOCSPTLCK, &unlock);
|
} else {
|
||||||
|
rc = enosys();
|
||||||
|
}
|
||||||
|
STRACE("unlockpt(%d) → %d% m", fd, rc);
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,10 @@
|
||||||
│ 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/mem/alg.h"
|
|
||||||
#include "libc/macros.internal.h"
|
#include "libc/macros.internal.h"
|
||||||
|
#include "libc/mem/alg.h"
|
||||||
#include "libc/nexgen32e/nexgen32e.h"
|
#include "libc/nexgen32e/nexgen32e.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/str/str.h"
|
#include "libc/str/str.h"
|
||||||
|
|
||||||
static const int kCp437iMultimappings[] = {
|
static const int kCp437iMultimappings[] = {
|
||||||
|
@ -76,7 +77,7 @@ static textstartup void g_cp437i_init() {
|
||||||
unsigned i;
|
unsigned i;
|
||||||
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
|
for (i = 0; i < 256; ++i) g_cp437i[i] = kCp437[i] << 8 | i;
|
||||||
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
|
memcpy(g_cp437i + 256, kCp437iMultimappings, sizeof(kCp437iMultimappings));
|
||||||
djbsort(g_cp437i, ARRAYLEN(g_cp437i));
|
_intsort(g_cp437i, ARRAYLEN(g_cp437i));
|
||||||
}
|
}
|
||||||
|
|
||||||
const void *const g_cp437i_ctor[] initarray = {g_cp437i_init};
|
const void *const g_cp437i_ctor[] initarray = {g_cp437i_init};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define LIBC_ISYSTEM_STDIO_H_
|
#define LIBC_ISYSTEM_STDIO_H_
|
||||||
#include "libc/calls/calls.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/fmt/fmt.h"
|
#include "libc/fmt/fmt.h"
|
||||||
|
#include "libc/mem/fmt.h"
|
||||||
#include "libc/stdio/lock.internal.h"
|
#include "libc/stdio/lock.internal.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/stdio/stdio.h"
|
||||||
#include "libc/stdio/temp.h"
|
#include "libc/stdio/temp.h"
|
||||||
|
|
4
libc/isystem/sysexits.h
Normal file
4
libc/isystem/sysexits.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_SYSEXITS_H_
|
||||||
|
#define COSMOPOLITAN_LIBC_ISYSTEM_SYSEXITS_H_
|
||||||
|
#include "libc/sysv/consts/ex.h"
|
||||||
|
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_SYSEXITS_H_ */
|
|
@ -1,30 +1,21 @@
|
||||||
#ifndef COSMOPOLITAN_LIBC_LOG_BSD_H_
|
#ifndef COSMOPOLITAN_LIBC_LOG_BSD_H_
|
||||||
#define COSMOPOLITAN_LIBC_LOG_BSD_H_
|
#define COSMOPOLITAN_LIBC_LOG_BSD_H_
|
||||||
#include "libc/fmt/pflink.h"
|
|
||||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
/*───────────────────────────────────────────────────────────────────────────│─╗
|
void err(int, const char *, ...) wontreturn;
|
||||||
│ cosmopolitan § logging » berkeley logger ─╬─│┼
|
void verr(int, const char *, va_list) wontreturn;
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
void errc(int, int, const char *, ...) wontreturn;
|
||||||
|
void verrc(int, int, const char *, va_list) wontreturn;
|
||||||
void err(int, const char *, ...) printfesque(2) wontreturn;
|
void errx(int, const char *, ...) wontreturn;
|
||||||
void errx(int, const char *, ...) printfesque(2) wontreturn;
|
void verrx(int, const char *, va_list) wontreturn;
|
||||||
void verr(int, const char *, va_list) paramsnonnull((3)) wontreturn;
|
void warn(const char *, ...);
|
||||||
void verrx(int, const char *, va_list) paramsnonnull((3)) wontreturn;
|
void vwarn(const char *, va_list);
|
||||||
void vwarn(const char *, va_list) paramsnonnull((2));
|
void warnc(int, const char *, ...);
|
||||||
void vwarnx(const char *, va_list) paramsnonnull((2));
|
void vwarnc(int, const char *, va_list);
|
||||||
void warn(const char *, ...) printfesque(1);
|
void warnx(const char *, ...);
|
||||||
void warnx(const char *, ...) printfesque(1);
|
void vwarnx(const char *, va_list);
|
||||||
|
void err_set_exit(void (*)(int));
|
||||||
#define err(EVAL, FMT, ...) (err)(EVAL, PFLINK(FMT), ##__VA_ARGS__)
|
|
||||||
#define errx(EVAL, FMT, ...) (errx)(EVAL, PFLINK(FMT), ##__VA_ARGS__)
|
|
||||||
#define verr(EVAL, FMT, VA) (verr)(EVAL, PFLINK(FMT), VA)
|
|
||||||
#define verrx(EVAL, FMT, VA) (verrx)(EVAL, PFLINK(FMT), VA)
|
|
||||||
#define vwarn(FMT, VA) (vwarn)(PFLINK(FMT), VA)
|
|
||||||
#define vwarnx(FMT, VA) (vwarnx)(PFLINK(FMT), VA)
|
|
||||||
#define warn(FMT, ...) (warn)(PFLINK(FMT), ##__VA_ARGS__)
|
|
||||||
#define warnx(FMT, ...) (warn)(PFLINK(FMT), ##__VA_ARGS__)
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
206
libc/log/err.c
206
libc/log/err.c
|
@ -1,26 +1,194 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
|
||||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
│vi: set et ft=c ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright (c) 1993 │
|
||||||
|
│ The Regents of the University of California. All rights reserved. │
|
||||||
│ │
|
│ │
|
||||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
│ Redistribution and use in source and binary forms, with or without │
|
||||||
│ any purpose with or without fee is hereby granted, provided that the │
|
│ modification, are permitted provided that the following conditions │
|
||||||
│ above copyright notice and this permission notice appear in all copies. │
|
│ are met: │
|
||||||
|
│ 1. Redistributions of source code must retain the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer. │
|
||||||
|
│ 2. Redistributions in binary form must reproduce the above copyright │
|
||||||
|
│ notice, this list of conditions and the following disclaimer in the │
|
||||||
|
│ documentation and/or other materials provided with the distribution. │
|
||||||
|
│ 3. Neither the name of the University nor the names of its contributors │
|
||||||
|
│ may be used to endorse or promote products derived from this software │
|
||||||
|
│ without specific prior written permission. │
|
||||||
│ │
|
│ │
|
||||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
│ THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND │
|
||||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
│ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE │
|
||||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
│ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE │
|
||||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
│ ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE │
|
||||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
│ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL │
|
||||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
│ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS │
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT │
|
||||||
|
│ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY │
|
||||||
|
│ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF │
|
||||||
|
│ SUCH DAMAGE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
|
#include "libc/errno.h"
|
||||||
#include "libc/log/bsd.h"
|
#include "libc/log/bsd.h"
|
||||||
|
#include "libc/runtime/runtime.h"
|
||||||
|
#include "libc/stdio/stdio.h"
|
||||||
|
#include "libc/str/str.h"
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
wontreturn void(err)(int eval, const char *fmt, ...) {
|
asm(".ident\t\"\\n\\n\
|
||||||
va_list va;
|
FreeBSD Err (BSD-3 License)\\n\
|
||||||
va_start(va, fmt);
|
Copyright (c) 1993\\n\
|
||||||
(verr)(eval, fmt, va);
|
\tThe Regents of the University of California.\\n\
|
||||||
va_end(va);
|
\tAll rights reserved.\"");
|
||||||
|
asm(".include \"libc/disclaimer.inc\"");
|
||||||
|
|
||||||
|
static FILE *err_file; /* file to use for error output */
|
||||||
|
static void (*err_exit)(int);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is declared to take a `void *' so that the caller is not required
|
||||||
|
* to include <stdio.h> first. However, it is really a `FILE *', and the
|
||||||
|
* manual page documents it as such.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
err_set_file(void *fp)
|
||||||
|
{
|
||||||
|
if (fp)
|
||||||
|
err_file = fp;
|
||||||
|
else
|
||||||
|
err_file = stderr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
err_set_exit(void (*ef)(int))
|
||||||
|
{
|
||||||
|
err_exit = ef;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
err(int eval, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
verrc(eval, errno, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
verr(int eval, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
verrc(eval, errno, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
errc(int eval, int code, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
verrc(eval, code, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
verrc(int eval, int code, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
if (err_file == NULL)
|
||||||
|
err_set_file(NULL);
|
||||||
|
fprintf(err_file, "%s: ", program_invocation_name);
|
||||||
|
if (fmt != NULL) {
|
||||||
|
vfprintf(err_file, fmt, ap);
|
||||||
|
fprintf(err_file, ": ");
|
||||||
|
}
|
||||||
|
fprintf(err_file, "%s\n", _strerdoc(code));
|
||||||
|
if (err_exit)
|
||||||
|
err_exit(eval);
|
||||||
|
exit(eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
errx(int eval, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
verrx(eval, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
verrx(int eval, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
if (err_file == NULL)
|
||||||
|
err_set_file(NULL);
|
||||||
|
fprintf(err_file, "%s: ", program_invocation_name);
|
||||||
|
if (fmt != NULL)
|
||||||
|
vfprintf(err_file, fmt, ap);
|
||||||
|
fprintf(err_file, "\n");
|
||||||
|
if (err_exit)
|
||||||
|
err_exit(eval);
|
||||||
|
exit(eval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warn(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vwarnc(errno, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vwarn(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
vwarnc(errno, fmt, ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warnc(int code, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vwarnc(code, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vwarnc(int code, const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
if (err_file == NULL)
|
||||||
|
err_set_file(NULL);
|
||||||
|
fprintf(err_file, "%s: ", program_invocation_name);
|
||||||
|
if (fmt != NULL) {
|
||||||
|
vfprintf(err_file, fmt, ap);
|
||||||
|
fprintf(err_file, ": ");
|
||||||
|
}
|
||||||
|
fprintf(err_file, "%s\n", strerror(code));
|
||||||
|
errno = saved_errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
warnx(const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vwarnx(fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
vwarnx(const char *fmt, va_list ap)
|
||||||
|
{
|
||||||
|
int saved_errno;
|
||||||
|
|
||||||
|
saved_errno = errno;
|
||||||
|
if (err_file == NULL)
|
||||||
|
err_set_file(NULL);
|
||||||
|
fprintf(err_file, "%s: ", program_invocation_name);
|
||||||
|
if (fmt != NULL)
|
||||||
|
vfprintf(err_file, fmt, ap);
|
||||||
|
fprintf(err_file, "\n");
|
||||||
|
errno = saved_errno;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +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/log/bsd.h"
|
|
||||||
#include "libc/log/color.internal.h"
|
|
||||||
#include "libc/log/internal.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
|
|
||||||
wontreturn void(verrx)(int eval, const char *fmt, va_list va) {
|
|
||||||
fprintf(stderr, "%s: %s%s%s: ", program_invocation_name, RED2, "ERROR",
|
|
||||||
RESET);
|
|
||||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
exit(eval);
|
|
||||||
}
|
|
|
@ -1,30 +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/log/bsd.h"
|
|
||||||
#include "libc/log/color.internal.h"
|
|
||||||
#include "libc/log/internal.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
|
|
||||||
void(vwarn)(const char *fmt, va_list va) {
|
|
||||||
fprintf(stderr, "%s: %s%s%s[%m]: ", program_invocation_name, SUBTLE,
|
|
||||||
"WARNING", RESET);
|
|
||||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
|
|
@ -1,26 +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/log/bsd.h"
|
|
||||||
|
|
||||||
void(warn)(const char *fmt, ...) {
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
(vwarn)(fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
|
@ -1,26 +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/log/bsd.h"
|
|
||||||
|
|
||||||
void(warnx)(const char *fmt, ...) {
|
|
||||||
va_list va;
|
|
||||||
va_start(va, fmt);
|
|
||||||
(vwarnx)(fmt, va);
|
|
||||||
va_end(va);
|
|
||||||
}
|
|
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2022 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,18 +16,37 @@
|
||||||
│ 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/safemacros.internal.h"
|
#include "libc/calls/calls.h"
|
||||||
#include "libc/log/bsd.h"
|
#include "libc/calls/ioctl.h"
|
||||||
#include "libc/log/color.internal.h"
|
#include "libc/calls/syscall-sysv.internal.h"
|
||||||
#include "libc/log/internal.h"
|
#include "libc/dce.h"
|
||||||
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
#include "libc/runtime/utmp.h"
|
||||||
|
#include "libc/sysv/consts/termios.h"
|
||||||
|
#include "libc/sysv/errfuns.h"
|
||||||
|
|
||||||
wontreturn void(verr)(int eval, const char *fmt, va_list va) {
|
/**
|
||||||
fprintf(stderr,
|
* Prepares terminal for login.
|
||||||
"%s: %s%s%s[%m]: ", firstnonnull(program_invocation_name, "unknown"),
|
*
|
||||||
RED2, "ERROR", RESET);
|
* @return 0 on success, or -1 w/ errno
|
||||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
* @raise ENOSYS on Windows and Metal
|
||||||
fprintf(stderr, "\n");
|
* @raise EPERM if terminal is already controlling another sid
|
||||||
exit(eval);
|
*/
|
||||||
|
int login_tty(int fd) {
|
||||||
|
int rc;
|
||||||
|
if (IsLinux() || IsBsd()) {
|
||||||
|
setsid();
|
||||||
|
if (!sys_ioctl(fd, TIOCSCTTY, 0)) {
|
||||||
|
for (int i = 0; i < 3; ++i) dup2(fd, i);
|
||||||
|
if (fd > 2) close(fd);
|
||||||
|
rc = 0;
|
||||||
|
} else {
|
||||||
|
rc = -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rc = enosys();
|
||||||
|
}
|
||||||
|
STRACE("login_tty(%d) → %d% m", fd, rc);
|
||||||
|
return rc;
|
||||||
}
|
}
|
|
@ -88,12 +88,14 @@ long gethostid(void);
|
||||||
int sethostid(long);
|
int sethostid(long);
|
||||||
char *getlogin(void);
|
char *getlogin(void);
|
||||||
int getlogin_r(char *, size_t);
|
int getlogin_r(char *, size_t);
|
||||||
|
int login_tty(int);
|
||||||
int getpagesize(void);
|
int getpagesize(void);
|
||||||
int syncfs(int);
|
int syncfs(int);
|
||||||
int vhangup(void);
|
int vhangup(void);
|
||||||
int getdtablesize(void);
|
int getdtablesize(void);
|
||||||
int sethostname(const char *, size_t);
|
int sethostname(const char *, size_t);
|
||||||
int acct(const char *);
|
int acct(const char *);
|
||||||
|
void _intsort(int *, size_t);
|
||||||
void _longsort(long *, size_t);
|
void _longsort(long *, size_t);
|
||||||
bool _isheap(void *);
|
bool _isheap(void *);
|
||||||
int NtGetVersion(void) pureconst;
|
int NtGetVersion(void) pureconst;
|
||||||
|
|
|
@ -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 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2021 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,15 +16,32 @@
|
||||||
│ 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/log/bsd.h"
|
#include "libc/intrin/strace.internal.h"
|
||||||
#include "libc/log/color.internal.h"
|
|
||||||
#include "libc/log/internal.h"
|
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
#include "libc/stdio/stdio.h"
|
|
||||||
|
|
||||||
void(vwarnx)(const char *fmt, va_list va) {
|
static void _intsorter(int *A, size_t n) {
|
||||||
fprintf(stderr, "%s: %s%s%s: ", program_invocation_name, SUBTLE, "WARNING",
|
int t, p;
|
||||||
RESET);
|
size_t i, j;
|
||||||
if (fmt) (vfprintf)(stderr, fmt, va);
|
if (n < 2) return;
|
||||||
fprintf(stderr, "\n");
|
for (p = A[n / 2], i = 0, j = n - 1;; i++, j--) {
|
||||||
|
while (A[i] < p) i++;
|
||||||
|
while (A[j] > p) j--;
|
||||||
|
if (i >= j) break;
|
||||||
|
t = A[i];
|
||||||
|
A[i] = A[j];
|
||||||
|
A[j] = t;
|
||||||
|
}
|
||||||
|
_intsorter(A, i);
|
||||||
|
_intsorter(A + i, n - i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tiny and reasonably fast sorting for ints.
|
||||||
|
* @see djbsort
|
||||||
|
*/
|
||||||
|
void _intsort(int *A, size_t n) {
|
||||||
|
_intsorter(A, n);
|
||||||
|
if (n > 1000) {
|
||||||
|
STRACE("_intsort(%p, %'zu)", A, n);
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1374,7 +1374,7 @@ syscon termios TIOCCONS 0x541d 0x80047462 0x80047462 0x80047462 0x800474
|
||||||
syscon termios TIOCGETD 0x5424 0x4004741a 0x4004741a 0x4004741a 0x4004741a 0 # boop
|
syscon termios TIOCGETD 0x5424 0x4004741a 0x4004741a 0x4004741a 0x4004741a 0 # boop
|
||||||
syscon termios TIOCNOTTY 0x5422 0x20007471 0x20007471 0x20007471 0x20007471 0 # boop
|
syscon termios TIOCNOTTY 0x5422 0x20007471 0x20007471 0x20007471 0x20007471 0 # boop
|
||||||
syscon termios TIOCNXCL 0x540d 0x2000740e 0x2000740e 0x2000740e 0x2000740e 0 # boop
|
syscon termios TIOCNXCL 0x540d 0x2000740e 0x2000740e 0x2000740e 0x2000740e 0 # boop
|
||||||
syscon termios TIOCSCTTY 0x540e 0x20007461 0x20007461 0x20007461 0x20007461 0 # boop
|
syscon termios TIOCSCTTY 0x540e 0x20007461 0x20007461 0x20007461 0x20007461 0 # makes terminal controlling terminal of calling process (see login_tty)
|
||||||
syscon termios TIOCSETD 0x5423 0x8004741b 0x8004741b 0x8004741b 0x8004741b 0 # boop
|
syscon termios TIOCSETD 0x5423 0x8004741b 0x8004741b 0x8004741b 0x8004741b 0 # boop
|
||||||
syscon termios TIOCSIG 0x40045436 0x2000745f 0x2004745f 0x8004745f 0x8004745f 0 # boop
|
syscon termios TIOCSIG 0x40045436 0x2000745f 0x2004745f 0x8004745f 0x8004745f 0 # boop
|
||||||
syscon termios TIOCSTI 0x5412 0x80017472 0x80017472 0 0 0 # boop
|
syscon termios TIOCSTI 0x5412 0x80017472 0x80017472 0 0 0 # boop
|
||||||
|
@ -1409,6 +1409,10 @@ syscon termios TIOCSFLAGS 0 0 0 0x8004745c 0x8004745c 0 # boop
|
||||||
syscon termios TIOCSTSTAMP 0 0 0 0x8008745a 0x8008745a 0 # boop
|
syscon termios TIOCSTSTAMP 0 0 0 0x8008745a 0x8008745a 0 # boop
|
||||||
syscon termios ENDRUNDISC 0 0 0 0x9 0x9 0 # boop
|
syscon termios ENDRUNDISC 0 0 0 0x9 0x9 0 # boop
|
||||||
syscon termios TIOCPTMASTER 0 0 0x2000741c 0 0 0 # boop
|
syscon termios TIOCPTMASTER 0 0 0x2000741c 0 0 0 # boop
|
||||||
|
syscon termios TIOCPTYGRANT 0 0x20007454 0 0 0 0 # xnu grantpt()
|
||||||
|
syscon termios TIOCPTYUNLK 0 0x20007452 0 0 0 0 # xnu grantpt()
|
||||||
|
syscon termios TIOCPTYGNAME 0 0x40807453 0 0 0 0 # xnu grantpt()
|
||||||
|
syscon termios FIODGNAME 0 0 0x80106678 0 0 0 # freebsd ptsname_r()
|
||||||
syscon termios NETGRAPHDISC 0 0 0x6 0 0 0 # boop
|
syscon termios NETGRAPHDISC 0 0 0x6 0 0 0 # boop
|
||||||
syscon termios H4DISC 0 0 0x7 0 0 0 # boop
|
syscon termios H4DISC 0 0 0x7 0 0 0 # boop
|
||||||
|
|
||||||
|
|
2
libc/sysv/consts/FIODGNAME.s
Normal file
2
libc/sysv/consts/FIODGNAME.s
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||||
|
.syscon termios,FIODGNAME,0,0,0x80106678,0,0,0
|
2
libc/sysv/consts/TIOCPTYGNAME.s
Normal file
2
libc/sysv/consts/TIOCPTYGNAME.s
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||||
|
.syscon termios,TIOCPTYGNAME,0,0x40807453,0,0,0,0
|
2
libc/sysv/consts/TIOCPTYGRANT.s
Normal file
2
libc/sysv/consts/TIOCPTYGRANT.s
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||||
|
.syscon termios,TIOCPTYGRANT,0,0x20007454,0,0,0,0
|
2
libc/sysv/consts/TIOCPTYUNLK.s
Normal file
2
libc/sysv/consts/TIOCPTYUNLK.s
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
.include "o/libc/sysv/consts/syscon.internal.inc"
|
||||||
|
.syscon termios,TIOCPTYUNLK,0,0x20007452,0,0,0,0
|
|
@ -2,6 +2,7 @@
|
||||||
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_POLL_H_
|
#define COSMOPOLITAN_LIBC_SYSV_CONSTS_POLL_H_
|
||||||
#include "libc/runtime/symbolic.h"
|
#include "libc/runtime/symbolic.h"
|
||||||
|
|
||||||
|
#define INFTIM (-1)
|
||||||
#define POLLERR SYMBOLIC(POLLERR)
|
#define POLLERR SYMBOLIC(POLLERR)
|
||||||
#define POLLHUP SYMBOLIC(POLLHUP)
|
#define POLLHUP SYMBOLIC(POLLHUP)
|
||||||
#define POLLIN SYMBOLIC(POLLIN)
|
#define POLLIN SYMBOLIC(POLLIN)
|
||||||
|
|
|
@ -178,6 +178,10 @@ extern const uint8_t VTIME;
|
||||||
extern const uint8_t VWERASE;
|
extern const uint8_t VWERASE;
|
||||||
extern const uint32_t XCASE;
|
extern const uint32_t XCASE;
|
||||||
extern const uint32_t XTABS;
|
extern const uint32_t XTABS;
|
||||||
|
extern const uint32_t FIODGNAME;
|
||||||
|
extern const uint32_t TIOCPTYGRANT;
|
||||||
|
extern const uint32_t TIOCPTYUNLK;
|
||||||
|
extern const uint32_t TIOCPTYGNAME;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
@ -250,6 +254,7 @@ COSMOPOLITAN_C_END_
|
||||||
#define EXTA SYMBOLIC(EXTA)
|
#define EXTA SYMBOLIC(EXTA)
|
||||||
#define EXTB SYMBOLIC(EXTB)
|
#define EXTB SYMBOLIC(EXTB)
|
||||||
#define EXTPROC SYMBOLIC(EXTPROC)
|
#define EXTPROC SYMBOLIC(EXTPROC)
|
||||||
|
#define FIODGNAME SYMBOLIC(FIODGNAME)
|
||||||
#define FLUSHO SYMBOLIC(FLUSHO)
|
#define FLUSHO SYMBOLIC(FLUSHO)
|
||||||
#define H4DISC SYMBOLIC(H4DISC)
|
#define H4DISC SYMBOLIC(H4DISC)
|
||||||
#define HUPCL SYMBOLIC(HUPCL)
|
#define HUPCL SYMBOLIC(HUPCL)
|
||||||
|
@ -319,6 +324,9 @@ COSMOPOLITAN_C_END_
|
||||||
#define TIOCNXCL SYMBOLIC(TIOCNXCL)
|
#define TIOCNXCL SYMBOLIC(TIOCNXCL)
|
||||||
#define TIOCOUTQ SYMBOLIC(TIOCOUTQ)
|
#define TIOCOUTQ SYMBOLIC(TIOCOUTQ)
|
||||||
#define TIOCPTMASTER SYMBOLIC(TIOCPTMASTER)
|
#define TIOCPTMASTER SYMBOLIC(TIOCPTMASTER)
|
||||||
|
#define TIOCPTYGNAME SYMBOLIC(TIOCPTYGNAME)
|
||||||
|
#define TIOCPTYGRANT SYMBOLIC(TIOCPTYGRANT)
|
||||||
|
#define TIOCPTYUNLK SYMBOLIC(TIOCPTYUNLK)
|
||||||
#define TIOCREMOTE SYMBOLIC(TIOCREMOTE)
|
#define TIOCREMOTE SYMBOLIC(TIOCREMOTE)
|
||||||
#define TIOCSBRK SYMBOLIC(TIOCSBRK)
|
#define TIOCSBRK SYMBOLIC(TIOCSBRK)
|
||||||
#define TIOCSCTTY SYMBOLIC(TIOCSCTTY)
|
#define TIOCSCTTY SYMBOLIC(TIOCSCTTY)
|
||||||
|
|
|
@ -55,17 +55,16 @@ enum PosixThreadStatus {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PosixThread {
|
struct PosixThread {
|
||||||
|
_Atomic(enum PosixThreadStatus) status;
|
||||||
void *(*start_routine)(void *);
|
void *(*start_routine)(void *);
|
||||||
void *arg; // start_routine's parameter
|
void *arg; // start_routine's parameter
|
||||||
void *rc; // start_routine's return value
|
void *rc; // start_routine's return value
|
||||||
bool ownstack;
|
bool ownstack; // should we free it
|
||||||
int tid;
|
int tid; // clone parent tid
|
||||||
int *ctid;
|
char *altstack; // thread sigaltstack
|
||||||
char *tls;
|
char *tls; // bottom of tls allocation
|
||||||
char *altstack;
|
struct CosmoTib *tib; // middle of tls allocation
|
||||||
struct CosmoTib *tib;
|
jmp_buf exiter; // for pthread_exit
|
||||||
_Atomic(enum PosixThreadStatus) status;
|
|
||||||
jmp_buf exiter;
|
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -82,7 +81,7 @@ void _pthread_wait(struct PosixThread *) hidden;
|
||||||
void _pthread_zombies_add(struct PosixThread *) hidden;
|
void _pthread_zombies_add(struct PosixThread *) hidden;
|
||||||
void _pthread_zombies_decimate(void) hidden;
|
void _pthread_zombies_decimate(void) hidden;
|
||||||
void _pthread_zombies_harvest(void) hidden;
|
void _pthread_zombies_harvest(void) hidden;
|
||||||
void _pthread_key_destruct(void *[PTHREAD_KEYS_MAX]);
|
void _pthread_key_destruct(void *[PTHREAD_KEYS_MAX]) hidden;
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
|
|
|
@ -73,6 +73,9 @@ o/$(MODE)/test/libc/sock/socket_test.com.runs: .INTERNET = 1 # todo: ipv6 filte
|
||||||
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
o/$(MODE)/test/libc/sock/socket_test.com.runs: \
|
||||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||||
|
|
||||||
|
o/$(MODE)/test/libc/sock/shutdown_test.com.runs: \
|
||||||
|
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||||
|
|
||||||
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/test/libc/sock
|
.PHONY: o/$(MODE)/test/libc/sock
|
||||||
|
|
Loading…
Reference in a new issue