Perform inconsequential code cleanup

This commit is contained in:
Justine Tunney 2023-08-07 20:22:49 -07:00
parent 929478c524
commit decf216655
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
52 changed files with 326 additions and 442 deletions

View file

@ -91,7 +91,7 @@ VM = o/third_party/qemu/qemu-aarch64
HOSTS ?= pi silicon
else
ARCH = x86_64
HOSTS ?= freebsd openbsd openbsd73 netbsd rhel7 rhel5 xnu win10
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
endif
ifeq ($(PREFIX),)

View file

@ -29,6 +29,7 @@
SUCH DAMAGE.
*/
#include "libc/calls/calls.h"
#include "libc/calls/weirdtypes.h"
#include "libc/dns/dns.h"
#include "libc/errno.h"
#include "libc/log/bsd.h"

View file

@ -56,9 +56,7 @@
*/
int close(int fd) {
int rc;
if (fd == -1) {
rc = 0;
} else if (fd < 0) {
if (fd < 0) {
rc = ebadf();
} else {
// for performance reasons we want to avoid holding __fds_lock()

View file

@ -17,7 +17,6 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/utsname-linux.internal.h"
#include "libc/calls/syscall_support-sysv.internal.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"

View file

@ -84,7 +84,9 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
}
if (IsMetal()) {
if (!memccpy(p, APE_COM_NAME, 0, e - p - 1)) e[-1] = 0;
if (!memccpy(p, APE_COM_NAME, 0, e - p - 1)) {
e[-1] = 0;
}
return;
}

View file

@ -38,6 +38,9 @@ int timespec_sleep_until(struct timespec);
struct timespec timespec_sub(struct timespec, struct timespec) pureconst;
struct timespec timespec_subz(struct timespec, struct timespec) pureconst;
int sys_futex(int *, int, int, const struct timespec *, int *);
static inline struct timespec timespec_fromseconds(int64_t __x) {
return (struct timespec){__x};
}
static inline bool timespec_iszero(struct timespec __ts) {
return !(__ts.tv_sec | __ts.tv_nsec);
}

View file

@ -30,7 +30,9 @@ struct timeval timeval_add(struct timeval, struct timeval) pureconst;
struct timeval timeval_sub(struct timeval, struct timeval) pureconst;
struct timeval timeval_subz(struct timeval, struct timeval) pureconst;
struct timeval timespec_totimeval(struct timespec) pureconst;
struct timespec timeval_totimespec(struct timeval) pureconst;
static inline struct timespec timeval_totimespec(struct timeval __tv) {
return (struct timespec){__tv.tv_sec, __tv.tv_usec * 1000};
}
static inline bool timeval_iszero(struct timeval __tv) {
return !(__tv.tv_sec | __tv.tv_usec);
}

View file

@ -37,10 +37,8 @@ int utimes(const char *path, const struct timeval tv[2]) {
int rc;
struct timespec ts[2];
if (tv) {
ts[0].tv_sec = tv[0].tv_sec;
ts[0].tv_nsec = tv[0].tv_usec * 1000;
ts[1].tv_sec = tv[1].tv_sec;
ts[1].tv_nsec = tv[1].tv_usec * 1000;
ts[0] = timeval_totimespec(tv[0]);
ts[1] = timeval_totimespec(tv[1]);
rc = __utimens(AT_FDCWD, path, ts, 0);
} else {
rc = __utimens(AT_FDCWD, path, 0, 0);

View file

@ -13,7 +13,7 @@ typedef uint64_t dev_t; /* int32_t on xnu */
typedef uint64_t fsblkcnt_t;
typedef int64_t fsfilcnt_t; /* uint32_t on xnu */
typedef uint32_t gid_t;
typedef uint32_t id_t; /* int32_t on linux/freebsd/etc. */
typedef int32_t id_t; /* int32_t on linux/freebsd/etc. */
typedef uint32_t in_addr_t;
typedef uint32_t in_addr_t;
typedef uint16_t in_port_t;

View file

@ -1,8 +1,6 @@
#ifndef COSMOPOLITAN_LIBC_DNS_DNS_H_
#define COSMOPOLITAN_LIBC_DNS_DNS_H_
#include "libc/calls/weirdtypes.h"
#include "libc/dns/resolvconf.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/sockaddr.h"
#define DNS_PORT 53
@ -67,8 +65,8 @@ struct addrinfo {
int getaddrinfo(const char *, const char *, const struct addrinfo *,
struct addrinfo **);
void freeaddrinfo(struct addrinfo *);
int getnameinfo(const struct sockaddr *, socklen_t, char *, socklen_t, char *,
socklen_t, int);
int getnameinfo(const struct sockaddr *, uint32_t, char *, uint32_t, char *,
uint32_t, int);
const char *gai_strerror(int);
int CompareDnsNames(const char *, const char *) paramsnonnull();
int PascalifyDnsName(uint8_t *, size_t, const char *) paramsnonnull();

View file

@ -57,7 +57,7 @@ void endprotoent(void);
struct hostent *gethostent(void);
struct hostent *gethostbyname(const char *);
struct hostent *gethostbyaddr(const void *, socklen_t, int);
struct hostent *gethostbyaddr(const void *, uint32_t, int);
void sethostent(int);
void endhostent(void);

View file

@ -22,7 +22,7 @@
#include "libc/dns/resolvconf.h"
#include "libc/dns/servicestxt.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/gc.h"
#include "libc/mem/mem.h"
#include "libc/sock/sock.h"
@ -94,7 +94,7 @@ int getaddrinfo(const char *name, const char *service,
return EAI_NONAME;
} else if (ResolveHostsTxt(GetHostsTxt(), AF_INET, name, ai->ai_addr,
sizeof(ai->ai_addr4), &canon) > 0) {
memcpy(ai->ai_canonname, canon, min(strlen(canon), DNS_NAME_MAX) + 1);
strlcpy(ai->ai_canonname, canon, DNS_NAME_MAX + 1);
*res = ai;
return 0;
} else {

View file

@ -28,7 +28,7 @@
#include "libc/mem/mem.h"
#include "libc/sysv/consts/af.h"
struct hostent *gethostbyaddr(const void *s_addr, socklen_t len, int type) {
struct hostent *gethostbyaddr(const void *s_addr, uint32_t len, int type) {
static struct hostent *ptr1, he1;
static char h_name[DNS_NAME_MAX + 1];
static char *h_aliases[1];

View file

@ -53,16 +53,16 @@ struct hostent *gethostbyname(const char *name) {
ptr0 = &he0;
}
if (getaddrinfo(name, NULL, NULL, &result) || result == NULL) return NULL;
if (getaddrinfo(name, NULL, NULL, &result) || result == NULL) {
return NULL;
}
/* if getaddrinfo is successful, result->ai_canonname is non-NULL,
* (see newaddrinfo) but the string can still be empty */
if (result->ai_canonname[0])
memccpy(ptr0->h_name, result->ai_canonname, '\0', DNS_NAME_MAX);
else
memccpy(ptr0->h_name, name, '\0', DNS_NAME_MAX);
strlcpy(ptr0->h_name, *result->ai_canonname ? result->ai_canonname : name,
sizeof(h_name));
*((uint32_t *)ptr0->h_addr_list[0]) = (result->ai_addr4->sin_addr.s_addr);
*((uint32_t *)ptr0->h_addr_list[0]) = result->ai_addr4->sin_addr.s_addr;
/* TODO: if result has ai_next, fit multiple entries for h_addr_list */
freeaddrinfo(result);

View file

@ -19,13 +19,13 @@
#include "libc/calls/calls.h"
#include "libc/dce.h"
#include "libc/dns/hoststxt.h"
#include "libc/dns/servicestxt.h"
#include "libc/fmt/fmt.h"
#include "libc/intrin/bits.h"
#include "libc/intrin/pushpop.internal.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
@ -39,16 +39,11 @@ static struct HostsTxtInitialStaticMemory {
char strings[64];
} g_hoststxt_init;
static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
uint32_t size) {
const char *const kWinHostsPath = "\\drivers\\etc\\hosts";
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
if (len && len + strlen(kWinHostsPath) + 1 < size) {
if (pathbuf[len] == '\\') pathbuf[len--] = '\0';
memcpy(&pathbuf[len], kWinHostsPath, strlen(kWinHostsPath) + 1);
return &pathbuf[0];
static const char *GetHostsTxtPath(char *path, size_t size) {
if (!IsWindows()) {
return "/etc/hosts";
} else {
return NULL;
return GetSystemDirectoryPath(path, size, "drivers\\etc\\hosts");
}
}
@ -60,8 +55,7 @@ static textwindows dontinline char *GetNtHostsTxtPath(char *pathbuf,
*/
const struct HostsTxt *GetHostsTxt(void) {
FILE *f;
const char *path;
char pathbuf[PATH_MAX];
char pathbuf[256];
struct HostsTxtInitialStaticMemory *init;
init = &g_hoststxt_init;
pthread_mutex_lock(&init->lock);
@ -72,11 +66,7 @@ const struct HostsTxt *GetHostsTxt(void) {
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
init->ht.strings.p = init->strings;
__cxa_atexit(FreeHostsTxt, &g_hoststxt, NULL);
path = "/etc/hosts";
if (IsWindows()) {
path = firstnonnull(GetNtHostsTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
}
if (fileexists(path) && (f = fopen(path, "r"))) {
if ((f = fopen(GetHostsTxtPath(pathbuf, sizeof(pathbuf)), "r"))) {
if (ParseHostsTxt(g_hoststxt, f) == -1) {
/* TODO(jart): Elevate robustness. */
}

View file

@ -53,8 +53,8 @@
*
* @return 0 on success or EAI_xxx value
*/
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *name,
socklen_t namelen, char *service, socklen_t servicelen,
int getnameinfo(const struct sockaddr *addr, uint32_t addrlen, char *name,
uint32_t namelen, char *service, uint32_t servicelen,
int flags) {
char *p, rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"];
char info[NI_MAXHOST + 1];

View file

@ -24,19 +24,14 @@
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/dns/prototxt.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
#include "libc/dns/servicestxt.h"
textwindows char *GetNtProtocolsTxtPath(char *pathbuf, uint32_t size) {
/* protocol, not plural */
const char *const kWinHostsPath = "\\drivers\\etc\\protocol";
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
if (len && len + strlen(kWinHostsPath) + 1 < size) {
if (pathbuf[len] == '\\') pathbuf[len--] = '\0';
memcpy(&pathbuf[len], kWinHostsPath, strlen(kWinHostsPath) + 1);
return &pathbuf[0];
const char *GetProtocolsTxtPath(char *buf, size_t size) {
if (!IsWindows()) {
return "/etc/protocols";
} else {
return NULL;
return GetSystemDirectoryPath(buf, size, "drivers\\etc\\protocol");
}
}

View file

@ -24,18 +24,13 @@
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/dns/servicestxt.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
textwindows char *GetNtServicesTxtPath(char *pathbuf, uint32_t size) {
const char *const kWinHostsPath = "\\drivers\\etc\\services";
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
if (len && len + strlen(kWinHostsPath) + 1 < size) {
if (pathbuf[len] == '\\') pathbuf[len--] = '\0';
memcpy(&pathbuf[len], kWinHostsPath, strlen(kWinHostsPath) + 1);
return &pathbuf[0];
const char *GetServicesTxtPath(char *path, size_t size) {
if (!IsWindows()) {
return "/etc/services";
} else {
return NULL;
return GetSystemDirectoryPath(path, size, "drivers\\etc\\services");
}
}

View file

@ -27,6 +27,7 @@
#include "libc/dns/ent.h"
#include "libc/dns/servicestxt.h"
#include "libc/mem/mem.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
struct servent *getservbyname(const char *name, const char *proto) {
@ -42,9 +43,10 @@ struct servent *getservbyname(const char *name, const char *proto) {
ptr0 = &se0;
}
if (proto) {
if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) return NULL;
} else
strcpy(localproto, "");
strlcpy(localproto, proto, sizeof(localproto));
} else {
*localproto = 0;
}
p = LookupServicesByName(name, ptr0->s_proto, DNS_NAME_MAX, ptr0->s_name,
DNS_NAME_MAX, NULL);
if (p == -1) return NULL;

View file

@ -41,9 +41,12 @@ struct servent *getservbyport(int port, const char *proto) {
ptr1 = &se1;
}
if (proto) {
if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) return NULL;
} else
strcpy(localproto, "");
if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) {
return NULL;
}
} else {
*localproto = 0;
}
if (LookupServicesByPort(ntohs(port), ptr1->s_proto, DNS_NAME_MAX,
ptr1->s_name, DNS_NAME_MAX, NULL) == -1) {
return NULL;

View file

@ -0,0 +1,37 @@
/*-*- 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 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
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/dns/dns.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
// e.g. GetSystemDirectoryPath(buf, size, "FOO") → "C:\WINDOWS\SYSTEM32\FOO"
textwindows char *GetSystemDirectoryPath(char *buf, size_t size,
const char *path) {
uint32_t syslen = GetSystemDirectoryA(buf, size);
size_t pathlen = strlen(path);
if (syslen && syslen + pathlen + 1 < size) {
if (buf[syslen] == '\\') {
--syslen;
}
memcpy(buf + syslen, path, pathlen + 1);
return buf;
} else {
return 0;
}
}

View file

@ -51,17 +51,16 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
const char *filepath) {
FILE *f;
char *line;
const char *path;
size_t linesize;
const char *path;
int found, result;
char pathbuf[PATH_MAX];
char pathbuf[256];
char *name, *number, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";
if (IsWindows()) {
path =
firstnonnull(GetNtProtocolsTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
}
path =
!IsWindows()
? "/etc/protocols"
: firstnonnull(GetProtocolsTxtPath(pathbuf, sizeof(pathbuf)), path);
}
if (bufsize == 0 || !(f = fopen(path, "r"))) {
return -1;
@ -70,18 +69,20 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
linesize = 0;
found = 0;
result = -1;
while (found == 0 && (getline(&line, &linesize, f)) != -1) {
while (found == 0 && getline(&line, &linesize, f) != -1) {
if ((comment = strchr(line, '#'))) *comment = '\0';
name = strtok_r(line, " \t\r\n\v", &tok);
number = strtok_r(NULL, "/ \t\r\n\v", &tok);
if (name && number) {
alias = name;
while (alias && strcasecmp(alias, protoname) != 0)
while (alias && strcasecmp(alias, protoname)) {
alias = strtok_r(NULL, " \t\r\n\v", &tok);
if (alias) /* alias matched with protoname */
{
}
if (alias) { /* alias matched with protoname */
if (!memccpy(buf, name, '\0', bufsize)) {
strcpy(buf, "");
if (bufsize) {
*buf = 0;
}
break;
}
result = atoi(number);

View file

@ -28,7 +28,6 @@
#include "libc/dns/prototxt.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/intrin/safemacros.internal.h"
#include "libc/macros.internal.h"
#include "libc/mem/mem.h"
#include "libc/str/str.h"
@ -46,28 +45,22 @@
* @param protonum is the protocol number
* @param buf is a buffer to store the official name of the protocol
* @param bufsize is the size of buf
* @param filepath is the location of the protocols file
* (if NULL, uses /etc/protocols)
* @param path is the location of the protocols file, which may be NULL
* to use the system-wide default
* @return 0 on success, -1 on error
* @note aliases are not read from the file.
*/
int LookupProtoByNumber(const int protonum, char *buf, size_t bufsize,
const char *filepath) {
const char *path) {
FILE *f;
char *line;
int found;
char *line;
size_t linesize;
const char *path;
char pathbuf[PATH_MAX];
char pathbuf[256];
char *name, *number, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/protocols";
if (IsWindows()) {
path =
firstnonnull(GetNtProtocolsTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
}
}
if (bufsize == 0 || !(f = fopen(path, "r"))) {
if (!bufsize ||
!(f = fopen(path ? path : GetProtocolsTxtPath(pathbuf, sizeof(pathbuf)),
"r"))) {
return -1;
}
line = NULL;

View file

@ -45,7 +45,7 @@
* @param buf is a buffer to store the official name of the service
* (if NULL, the official name is not stored)
* @param bufsize is the size of buf
* @param filepath is the location of services file
* @param path is the location of services file
* (if NULL, uses /etc/services)
* @return -1 on error, or positive port number
* @note aliases are read from file for comparison, but not returned.
@ -54,29 +54,23 @@
*/
int LookupServicesByName(const char *servname, char *servproto,
size_t servprotolen, char *buf, size_t bufsize,
const char *filepath) {
const char *path) {
FILE *f;
char *line;
const char *path;
size_t linesize;
char pathbuf[256];
int found, result;
char pathbuf[PATH_MAX];
char *name, *port, *proto, *alias, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/services";
if (IsWindows()) {
path =
firstnonnull(GetNtServicesTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
}
}
if (servprotolen == 0 || !(f = fopen(path, "r"))) {
if (servprotolen == 0 ||
!(f = fopen(path ? path : GetServicesTxtPath(pathbuf, sizeof(pathbuf)),
"r"))) {
return -1;
}
line = NULL;
linesize = 0;
found = 0;
result = -1;
if (buf && bufsize != 0) strcpy(buf, "");
if (bufsize) strcpy(buf, "");
while (found == 0 && (getline(&line, &linesize, f)) != -1) {
if ((comment = strchr(line, '#'))) *comment = '\0';
name = strtok_r(line, " \t\r\n\v", &tok);
@ -93,8 +87,8 @@ int LookupServicesByName(const char *servname, char *servproto,
strcpy(servproto, "");
break;
}
if (buf && bufsize != 0 && !memccpy(buf, name, '\0', bufsize)) {
strcpy(buf, "");
if (bufsize && !memccpy(buf, name, '\0', bufsize)) {
*buf = 0;
break;
}
result = atoi(port);

View file

@ -52,36 +52,30 @@
* @param servprotolen the size of servproto
* @param buf is a buffer to store the official name of the service
* @param bufsize is the size of buf
* @param filepath is the location of the services file
* (if NULL, uses /etc/services)
* @param path is the location of the services file, which may be NULL
* to use the system-wide default
* @return 0 on success, -1 on error
* @note aliases are not read from the file.
*/
int LookupServicesByPort(const int servport, char *servproto,
size_t servprotolen, char *buf, size_t bufsize,
const char *filepath) {
const char *path) {
FILE *f;
char *line;
char pathbuf[PATH_MAX];
const char *path;
size_t linesize;
int found;
char *line;
size_t linesize;
char pathbuf[256];
char *name, *port, *proto, *comment, *tok;
if (!(path = filepath)) {
path = "/etc/services";
if (IsWindows()) {
path =
firstnonnull(GetNtServicesTxtPath(pathbuf, ARRAYLEN(pathbuf)), path);
}
}
if (servprotolen == 0 || bufsize == 0 || !(f = fopen(path, "r"))) {
if (!servprotolen ||
!(f = fopen(path ? path : GetServicesTxtPath(pathbuf, sizeof(pathbuf)),
"r"))) {
return -1;
}
found = 0;
line = NULL;
linesize = 0;
found = 0;
strcpy(buf, "");
while (found == 0 && (getline(&line, &linesize, f)) != -1) {
if (bufsize) *buf = 0;
while (!found && (getline(&line, &linesize, f)) != -1) {
if ((comment = strchr(line, '#'))) *comment = '\0';
name = strtok_r(line, " \t\r\n\v", &tok);
port = strtok_r(NULL, "/ \t\r\n\v", &tok);
@ -93,7 +87,9 @@ int LookupServicesByPort(const int servport, char *servproto,
break;
}
if (!memccpy(buf, name, '\0', bufsize)) {
strcpy(buf, "");
if (bufsize) {
*buf = 0;
}
break;
}
found = 1;

View file

@ -22,7 +22,7 @@
#include "libc/sock/sock.h"
#include "libc/sysv/consts/af.h"
#define SIZE ROUNDUP(sizeof(struct addrinfo), sizeof(void *))
#define SIZE sizeof(struct addrinfo)
#define ADDRLEN sizeof(struct sockaddr_in)
struct addrinfo *newaddrinfo(uint16_t port) {

View file

@ -5,11 +5,12 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
const char *GetProtocolsTxtPath(char *, size_t);
int LookupProtoByNumber(const int, char *, size_t, const char *)
paramsnonnull((2));
int LookupProtoByName(const char *, char *, size_t, const char *)
paramsnonnull((1, 2));
char *GetNtProtocolsTxtPath(char *, uint32_t);
/* TODO: implement like struct HostsTxt? */

View file

@ -44,7 +44,7 @@ int ResolveHostsReverse(const struct HostsTxt *ht, int af, const uint8_t *ip,
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
for (i = 0; i < ht->entries.i; ++i) {
if (READ32LE(ip) == READ32LE(ht->entries.p[i].ip)) {
if (memccpy(buf, ht->strings.p + ht->entries.p[i].name, '\0', bufsize)) {
if (memccpy(buf, ht->strings.p + ht->entries.p[i].name, 0, bufsize)) {
return 1;
}
}

View file

@ -5,11 +5,12 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
char *GetSystemDirectoryPath(char *, size_t, const char *);
int LookupServicesByPort(const int, char *, size_t, char *, size_t,
const char *) paramsnonnull((2, 4));
int LookupServicesByName(const char *, char *, size_t, char *, size_t,
const char *) paramsnonnull((1, 2));
char *GetNtServicesTxtPath(char *, uint32_t);
const char *GetServicesTxtPath(char *, size_t);
/* TODO: implement like struct HostsTxt? */

View file

@ -1,19 +1,7 @@
/*
* Copyright 2023 Justine Alexandra Roberts Tunney
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* 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.
*/
#ifndef COSMOPOLITAN_LIBC_STDCKDINT_H_
#define COSMOPOLITAN_LIBC_STDCKDINT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
/* clang-format off */
/**
* @fileoverview C23 Checked Arithmetic
@ -54,16 +42,6 @@
* @version 0.1 (2023-07-22)
*/
#ifndef JTCKDINT_H_
#define JTCKDINT_H_
/* clang-format off */
#ifdef __has_include
#define __ckd_has_include(x) __has_include(x)
#else
#define __ckd_has_include(x) 0
#endif
#define __STDC_VERSION_STDCKDINT_H__ 202311L
#if ((defined(__llvm__) || \
@ -81,18 +59,12 @@
typedef signed __ckd_intmax __ckd_intmax_t;
typedef unsigned __ckd_intmax __ckd_uintmax_t;
#ifdef __has_builtin
#define __ckd_has_builtin(x) __has_builtin(x)
#else
#define __ckd_has_builtin(x) 0
#endif
#if (!defined(__STRICT_ANSI__) && \
((defined(__GNUC__) && __GNUC__ >= 5 && \
!defined(__chibicc__) && !defined(__ICC)) || \
(__ckd_has_builtin(__builtin_add_overflow) && \
__ckd_has_builtin(__builtin_sub_overflow) && \
__ckd_has_builtin(__builtin_mul_overflow))))
#if (!defined(__STRICT_ANSI__) && \
((defined(__GNUC__) && __GNUC__ >= 5 && \
!defined(__chibicc__) && !defined(__ICC)) || \
(__has_builtin(__builtin_add_overflow) && \
__has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))))
#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res))
#define ckd_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_overflow((x), (y), (res))
@ -653,4 +625,5 @@ __ckd_declare_mul(__ckd_mul_uint128, unsigned __int128)
#define ckd_mul(res, x, y) (*(res) = (x) * (y), 0)
#endif /* GNU */
#endif /* JTCKDINT_H_ */
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_STDCKDINT_H_ */

View file

@ -47,7 +47,7 @@ int fclose(FILE *f) {
f->state = EOF;
if (f->noclose) {
f->fd = -1;
} else if (close(f->fd) == -1) {
} else if (f->fd != -1 && close(f->fd) == -1) {
f->state = errno;
}
if (f->state == EOF) {

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,11 +16,16 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/calls/struct/timeval.h"
#include "libc/fmt/conv.h"
#include "third_party/gdtoa/gdtoa.h"
/**
* Coerces `tv` from 1e-6 to 1e-9 granularity.
* Converts string to long double.
*/
struct timespec timeval_totimespec(struct timeval tv) {
return (struct timespec){tv.tv_sec, tv.tv_usec * 1000};
long double strtold(const char *s, char **endptr) {
long double x;
strtorx(s, endptr, FPI_Round_near, &x);
return x;
}
__weak_reference(strtold, strtold_l);

View file

@ -71,8 +71,8 @@ int system(const char *cmdline) {
break;
}
}
sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0);
sigaction(SIGINT, &saveint, 0);
}
sigprocmask(SIG_SETMASK, &savemask, 0);
ALLOW_CANCELLATIONS;

View file

@ -46,11 +46,11 @@
* @asyncsignalsafe
*/
void *memccpy(void *dst, const void *src, int c, size_t n) {
char *d;
size_t i;
unsigned char *d;
const unsigned char *s;
const char *s;
for (d = dst, s = src, i = 0; i < n; ++i) {
if ((d[i] = s[i]) == (c & 255)) {
if (((d[i] = s[i]) & 255) == (c & 255)) {
return d + i + 1;
}
}

View file

@ -16,27 +16,30 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/str/str.h"
/**
* Prepares static search buffer.
*
* 1. If SRC is too long, it's truncated and *not* NUL-terminated.
*
* 2. If SRC is too short, the remainder is zero-filled.
*
* Please note this function isn't designed to prevent untrustworthy
* data from modifying memory without authorization. Consider trying
* memccpy() for that purpose.
*
* @return dest + stride
* @see stncpy(), memccpy()
* @param dst is output buffer
* @param src is a nul-terminated string
* @param dstlen is size of `dst` buffer
* @return pointer to first nul-terminator, otherwise dest + stride
* @asyncsignalsafe
* @see strncpy()
* @see memccpy()
* @see strlcpy()
*/
char *stpncpy(char *dest, const char *src, size_t stride) {
char *p;
if ((p = memccpy(dest, src, '\0', stride))) {
bzero(p, dest + stride - p);
}
return dest + stride;
char *stpncpy(char *dst, const char *src, size_t dstlen) {
size_t srclen, cpylen, zerlen;
srclen = strlen(src);
cpylen = MIN(srclen, dstlen);
if (cpylen) memcpy(dst, src, cpylen);
zerlen = dstlen - cpylen;
if (zerlen) bzero(dst + cpylen, zerlen);
return dst + cpylen;
}

View file

@ -27,12 +27,14 @@
* @param 𝑛 is maximum number of characters from s to copy
* @return 𝑑
* @note 𝑑 and 𝑠 can't overlap
* @asyncsignaslenafe
* @asyncsignalsafe
*/
char *strncat(char *d, const char *s, size_t n) {
size_t o;
if (!memccpy(d + (o = strlen(d)), s, '\0', n)) {
d[o + n] = '\0';
size_t dn, sn;
if ((sn = strnlen(s, n))) {
dn = strlen(d);
memcpy(d + dn, s, sn);
d[dn + sn] = 0;
}
return d;
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/macros.internal.h"
#include "libc/str/str.h"
/**
@ -24,16 +25,21 @@
* 1. If SRC is too long, it's truncated and *not* NUL-terminated.
* 2. If SRC is too short, the remainder is zero-filled.
*
* @return dest
* @see stpncpy(), memccpy()
* @param dst is output buffer
* @param src is a nul-terminated string
* @param dstlen is size of `dst` buffer
* @return dst
* @asyncsignalsafe
* @vforksafe
* @see stpncpy()
* @see strlcpy()
* @see memccpy()
*/
char *strncpy(char *dest, const char *src, size_t stride) {
size_t i;
for (i = 0; i < stride; ++i) {
if (!(dest[i] = src[i])) break;
}
bzero(dest + i, stride - i);
return dest;
char *strncpy(char *dst, const char *src, size_t dstlen) {
size_t srclen, cpylen, zerlen;
srclen = strlen(src);
cpylen = MIN(srclen, dstlen);
if (cpylen) memcpy(dst, src, cpylen);
zerlen = dstlen - cpylen;
if (zerlen) bzero(dst + cpylen, zerlen);
return dst;
}

View file

@ -28,64 +28,26 @@
#include "libc/testlib/testlib.h"
#include "libc/thread/spawn.h"
////////////////////////////////////////////////////////////////////////////////
// SIGTRAP
TEST(raise, trap_sysv) {
if (IsWindows()) return;
TEST(raise, trap) {
signal(SIGTRAP, SIG_DFL);
SPAWN(fork);
raise(SIGTRAP);
TERMS(SIGTRAP);
}
TEST(raise, trap_windows) {
if (!IsWindows()) return;
signal(SIGTRAP, SIG_DFL);
SPAWN(fork);
raise(SIGTRAP);
EXITS(128 + SIGTRAP);
}
////////////////////////////////////////////////////////////////////////////////
// SIGFPE
TEST(raise, fpe_sysv) {
if (IsWindows()) return;
TEST(raise, fpe) {
signal(SIGFPE, SIG_DFL);
SPAWN(fork);
raise(SIGFPE);
TERMS(SIGFPE);
}
TEST(raise, fpe_windows) {
if (!IsWindows()) return;
signal(SIGFPE, SIG_DFL);
SPAWN(fork);
raise(SIGFPE);
EXITS(128 + SIGFPE);
}
////////////////////////////////////////////////////////////////////////////////
// SIGUSR1
TEST(raise, usr1_sysv) {
if (IsWindows()) return;
TEST(raise, usr1) {
SPAWN(fork);
raise(SIGUSR1);
TERMS(SIGUSR1);
}
TEST(raise, usr1_windows) {
if (!IsWindows()) return;
SPAWN(fork);
raise(SIGUSR1);
EXITS(128 + SIGUSR1);
}
////////////////////////////////////////////////////////////////////////////////
// THREADS
int threadid;
void WorkerQuit(int sig, siginfo_t *si, void *ctx) {

View file

@ -25,10 +25,10 @@
OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/dns/servicestxt.h"
#include "libc/calls/calls.h"
#include "libc/dns/dns.h"
#include "libc/dns/ent.h"
#include "libc/dns/servicestxt.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
@ -137,8 +137,8 @@ TEST(LookupServicesByName, GetPortWhenNameOrAlias) {
localproto = proto2;
ASSERT_EQ(-1, /* protocol is non-NULL/length must be nonzero */
LookupServicesByName("ssh", localproto, 0, name, sizeof(name),
"services"));
LookupServicesByName("ssh", localproto, sizeof(proto2), name,
sizeof(name), "services"));
ASSERT_STREQ(proto2, "udp");
localproto = proto1;

View file

@ -19,33 +19,20 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/subprocess.h"
#include "libc/testlib/testlib.h"
TEST(abort, sysv) {
if (IsWindows()) return;
TEST(abort, test) {
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
abort();
TERMS(SIGABRT);
}
TEST(abort, windows) {
if (!IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
abort();
EXITS(128 + SIGABRT);
}
////////////////////////////////////////////////////////////////////////////////
TEST(abort, blocked_stillTerminates_sysv) {
TEST(abort, blocked_stillTerminates) {
sigset_t ss;
if (IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
sigfillset(&ss);
@ -54,52 +41,19 @@ TEST(abort, blocked_stillTerminates_sysv) {
TERMS(SIGABRT);
}
TEST(abort, blocked_stillTerminates_windows) {
sigset_t ss;
if (!IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
sigfillset(&ss);
sigprocmask(SIG_SETMASK, &ss, 0);
abort();
EXITS(128 + SIGABRT);
}
////////////////////////////////////////////////////////////////////////////////
TEST(abort, ign_stillTerminates_sysv) {
if (IsWindows()) return;
TEST(abort, ign_stillTerminates) {
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN));
abort();
TERMS(SIGABRT);
}
TEST(abort, ign_stillTerminates_windows) {
if (!IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN));
abort();
EXITS(128 + SIGABRT);
}
////////////////////////////////////////////////////////////////////////////////
void Ignore(int sig) {
}
TEST(abort, handled_stillTerminates_sysv) {
if (IsWindows()) return;
TEST(abort, handled_stillTerminates) {
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore));
abort();
TERMS(SIGABRT);
}
TEST(abort, handled_stillTerminates_windows) {
if (!IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore));
abort();
EXITS(128 + SIGABRT);
}

View file

@ -1,7 +1,7 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2022 Justine Alexandra Roberts Tunney
Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
@ -16,24 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/thread/thread.h"
#include "third_party/gdtoa/lock.h"
#include "libc/str/str.h"
#include "libc/testlib/testlib.h"
static pthread_mutex_t __gdtoa_lock_obj;
static pthread_mutex_t __gdtoa_lock1_obj;
int(__gdtoa_lock)(void) {
return pthread_mutex_lock(&__gdtoa_lock_obj);
}
int(__gdtoa_unlock)(void) {
return pthread_mutex_unlock(&__gdtoa_lock_obj);
}
int(__gdtoa_lock1)(void) {
return pthread_mutex_lock(&__gdtoa_lock1_obj);
}
int(__gdtoa_unlock1)(void) {
return pthread_mutex_unlock(&__gdtoa_lock1_obj);
TEST(strncat, test) {
char buf[32] = "foo";
EXPECT_STREQ("foobar", strncat(buf, "bar", 3));
EXPECT_STREQ("foobarbar", strncat(buf, "bar", 10));
EXPECT_STREQ("foobarbarb", strncat(buf, "bar", 1));
EXPECT_STREQ("foobarbarb", strncat(buf, "", 1));
}

View file

@ -1,27 +0,0 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_
#define COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_
#include "libc/intrin/nopl.internal.h"
#include "libc/thread/tls.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
int __gdtoa_lock(void);
int __gdtoa_unlock(void);
int __gdtoa_lock1(void);
int __gdtoa_unlock1(void);
#ifdef _NOPL0
#define __gdtoa_lock() _NOPL0("__threadcalls", __gdtoa_lock)
#define __gdtoa_unlock() _NOPL0("__threadcalls", __gdtoa_unlock)
#define __gdtoa_lock1() _NOPL0("__threadcalls", __gdtoa_lock1)
#define __gdtoa_unlock1() _NOPL0("__threadcalls", __gdtoa_unlock1)
#else
#define __gdtoa_lock() (__threaded ? __gdtoa_lock() : 0)
#define __gdtoa_unlock() (__threaded ? __gdtoa_unlock() : 0)
#define __gdtoa_lock1() (__threaded ? __gdtoa_lock1() : 0)
#define __gdtoa_unlock1() (__threaded ? __gdtoa_unlock1() : 0)
#endif
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_THIRD_PARTY_GDTOA_LOCK_H_ */

View file

@ -32,11 +32,58 @@
#include "libc/calls/calls.h"
#include "libc/macros.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/thread/thread.h"
#include "libc/thread/tls.h"
#include "third_party/gdtoa/gdtoa.internal.h"
#include "third_party/gdtoa/lock.h"
/* clang-format off */
static ThInfo TI0;
static pthread_mutex_t __gdtoa_lock_obj;
static pthread_mutex_t __gdtoa_lock1_obj;
static void
__gdtoa_lock(void)
{
if (!__threaded)
return;
pthread_mutex_lock(&__gdtoa_lock_obj);
}
static void
__gdtoa_unlock(void)
{
if (!__threaded)
return;
pthread_mutex_unlock(&__gdtoa_lock_obj);
}
static void
__gdtoa_initlock(void)
{
pthread_mutex_init(&__gdtoa_lock_obj, 0);
}
static void
__gdtoa_lock1(void)
{
if (!__threaded)
return;
pthread_mutex_lock(&__gdtoa_lock1_obj);
}
static void
__gdtoa_unlock1(void)
{
if (!__threaded)
return;
pthread_mutex_unlock(&__gdtoa_lock1_obj);
}
static void
__gdtoa_initlock1(void)
{
pthread_mutex_init(&__gdtoa_lock1_obj, 0);
}
static void
__gdtoa_Brelease(Bigint *rv)
@ -63,7 +110,11 @@ __gdtoa_Bclear(void)
__attribute__((__constructor__)) static void
__gdtoa_Binit(void)
{
__gdtoa_initlock();
__gdtoa_initlock1();
atexit(__gdtoa_Bclear);
pthread_atfork(__gdtoa_lock1, __gdtoa_unlock1, __gdtoa_initlock1);
pthread_atfork(__gdtoa_lock, __gdtoa_unlock, __gdtoa_initlock);
}
static ThInfo *

View file

@ -1,44 +0,0 @@
/*-*- 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
The author of this software is David M. Gay.
Please send bug reports to David M. Gay <dmg@acm.org>
or Justine Tunney <jtunney@gmail.com>
Copyright (C) 1998, 1999 by Lucent Technologies
All Rights Reserved
Permission to use, copy, modify, and distribute this software and
its documentation for any purpose and without fee is hereby
granted, provided that the above copyright notice appear in all
copies and that both that the copyright notice and this
permission notice and warranty disclaimer appear in supporting
documentation, and that the name of Lucent or any of its entities
not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior
permission.
LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
SPECIAL, 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/fmt/conv.h"
#include "third_party/gdtoa/gdtoa.h"
/**
* Converts string to long double.
*/
long double strtold(const char *s, char **endptr) {
long double x;
strtorx(s, endptr, FPI_Round_near, &x);
return x;
}
__weak_reference(strtold, strtold_l);

View file

@ -38,6 +38,7 @@
#include "libc/calls/struct/timeval.h"
#include "libc/calls/struct/winsize.h"
#include "libc/calls/ucontext.h"
#include "libc/calls/weirdtypes.h"
#include "libc/dce.h"
#include "libc/dns/dns.h"
#include "libc/errno.h"

View file

@ -15,8 +15,10 @@
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "third_party/mbedtls/net_sockets.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/weirdtypes.h"
#include "libc/dns/dns.h"
#include "libc/errno.h"
#include "libc/sock/select.h"
@ -31,7 +33,6 @@
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/sol.h"
#include "third_party/mbedtls/error.h"
#include "third_party/mbedtls/net_sockets.h"
#include "third_party/mbedtls/ssl.h"
#define IS_EINTR(ret) ((ret) == EINTR)

View file

@ -97,6 +97,7 @@ void mbedtls_test_platform_teardown(void) {
}
wontreturn void exit(int rc) {
if (rc) fprintf(stderr, "mbedtls test exit() called with %d\n", rc);
if (rc) xwrite(1, output, appendz(output).i);
free(output);
output = 0;

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/stat.h"
#include "libc/calls/struct/timespec.h"
#include "libc/calls/struct/timeval.h"
#include "libc/dce.h"
#include "libc/errno.h"
@ -97,7 +98,7 @@
* - 1 byte exit status
*/
#define DEATH_CLOCK_SECONDS 128
#define DEATH_CLOCK_SECONDS 300
#define kLogFile "o/runitd.log"
#define kLogMaxBytes (2 * 1000 * 1000)
@ -123,7 +124,6 @@ void OnChildTerminated(int sig) {
sigdelset(&ss, SIGTERM);
sigprocmask(SIG_BLOCK, &ss, &oldss);
for (;;) {
INFOF("waitpid");
if ((pid = waitpid(-1, &ws, WNOHANG)) != -1) {
if (pid) {
if (WIFEXITED(ws)) {
@ -364,13 +364,12 @@ void HandleClient(void) {
const size_t kMaxNameSize = 128;
const size_t kMaxFileSize = 10 * 1024 * 1024;
uint32_t crc;
sigset_t sigmask;
ssize_t got, wrote;
struct sockaddr_in addr;
long double now, deadline;
sigset_t chldmask, savemask;
struct timespec now, deadline;
char *addrstr, *exename, *exe;
unsigned char msg[4 + 1 + 4 + 4 + 4];
struct sigaction ignore, saveint, savequit;
uint32_t addrsize, namesize, filesize, remaining;
int rc, events, exitcode, wstatus, child, pipefds[2];
@ -411,29 +410,24 @@ void HandleClient(void) {
}
CHECK_NE(-1, (g_exefd = creat(g_exepath, 0700)));
LOGIFNEG1(ftruncate(g_exefd, filesize));
INFOF("xwrite");
CHECK_NE(-1, xwrite(g_exefd, exe, filesize));
LOGIFNEG1(close(g_exefd));
/* run program, tee'ing stderr to both log and client */
DEBUGF("spawning %s", exename);
ignore.sa_flags = 0;
ignore.sa_handler = SIG_IGN;
sigemptyset(&ignore.sa_mask);
sigaction(SIGINT, &ignore, &saveint);
sigaction(SIGQUIT, &ignore, &savequit);
sigemptyset(&chldmask);
sigaddset(&chldmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &chldmask, &savemask);
sigemptyset(&sigmask);
sigaddset(&sigmask, SIGINT);
sigaddset(&sigmask, SIGQUIT);
sigaddset(&sigmask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigmask, 0);
CHECK_NE(-1, pipe2(pipefds, O_CLOEXEC));
CHECK_NE(-1, (child = fork()));
if (!child) {
dup2(g_bogusfd, 0);
dup2(pipefds[1], 1);
dup2(pipefds[1], 2);
sigaction(SIGINT, &(struct sigaction){0}, 0);
sigaction(SIGQUIT, &(struct sigaction){0}, 0);
sigprocmask(SIG_SETMASK, &savemask, 0);
sigemptyset(&sigmask);
sigprocmask(SIG_SETMASK, &sigmask, 0);
int i = 0;
const char *exe;
char *args[8] = {0};
@ -451,13 +445,17 @@ void HandleClient(void) {
execvp(exe, args);
_Exit(127);
}
signal(SIGINT, SIG_IGN);
signal(SIGQUIT, SIG_IGN);
close(pipefds[1]);
DEBUGF("communicating %s[%d]", exename, child);
deadline = nowl() + DEATH_CLOCK_SECONDS;
deadline =
timespec_add(timespec_real(), timespec_fromseconds(DEATH_CLOCK_SECONDS));
for (;;) {
now = nowl();
if (now >= deadline) {
now = timespec_real();
if (timespec_cmp(now, deadline) >= 0) {
WARNF("%s worker timed out", exename);
TerminateJob:
LOGIFNEG1(kill(child, 9));
LOGIFNEG1(waitpid(child, 0, 0));
LOGIFNEG1(close(g_clifd));
@ -470,31 +468,31 @@ void HandleClient(void) {
fds[0].events = POLLIN;
fds[1].fd = pipefds[0];
fds[1].events = POLLIN;
INFOF("poll");
events = poll(fds, ARRAYLEN(fds), (deadline - now) * 1000);
int waitms = timespec_tomillis(timespec_sub(deadline, now));
INFOF("polling for %d ms", waitms);
events = poll(fds, ARRAYLEN(fds), waitms);
CHECK_NE(-1, events); // EINTR shouldn't be possible
if (fds[0].revents) {
if (!(fds[0].revents & POLLHUP)) {
WARNF("%s got unexpected input event from client %#x", exename,
fds[0].revents);
if (events) {
if (fds[0].revents) {
if (!(fds[0].revents & POLLHUP)) {
WARNF("%s got unexpected input event from client %#x", exename,
fds[0].revents);
}
WARNF("%s client disconnected so killing worker %d", exename, child);
goto TerminateJob;
}
if (fds[1].revents) {
INFOF("read");
got = read(pipefds[0], g_buf, sizeof(g_buf));
CHECK_NE(-1, got); // EINTR shouldn't be possible
if (!got) {
LOGIFNEG1(close(pipefds[0]));
break;
}
fwrite(g_buf, got, 1, stderr);
SendOutputFragmentMessage(kRunitStderr, g_buf, got);
}
WARNF("%s client disconnected so killing worker %d", exename, child);
LOGIFNEG1(kill(child, 9));
LOGIFNEG1(waitpid(child, 0, 0));
LOGIFNEG1(close(g_clifd));
LOGIFNEG1(close(pipefds[0]));
LOGIFNEG1(unlink(g_exepath));
_exit(1);
}
INFOF("read");
got = read(pipefds[0], g_buf, sizeof(g_buf));
CHECK_NE(-1, got); // EINTR shouldn't be possible
if (!got) {
LOGIFNEG1(close(pipefds[0]));
break;
}
fwrite(g_buf, got, 1, stderr);
SendOutputFragmentMessage(kRunitStderr, g_buf, got);
}
INFOF("waitpid");
CHECK_NE(-1, waitpid(child, &wstatus, 0)); // EINTR shouldn't be possible