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 HOSTS ?= pi silicon
else else
ARCH = x86_64 ARCH = x86_64
HOSTS ?= freebsd openbsd openbsd73 netbsd rhel7 rhel5 xnu win10 HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
endif endif
ifeq ($(PREFIX),) ifeq ($(PREFIX),)

View file

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

View file

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

View file

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

View file

@ -84,7 +84,9 @@ static inline void GetProgramExecutableNameImpl(char *p, char *e) {
} }
if (IsMetal()) { 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; 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_sub(struct timespec, struct timespec) pureconst;
struct timespec timespec_subz(struct timespec, struct timespec) pureconst; struct timespec timespec_subz(struct timespec, struct timespec) pureconst;
int sys_futex(int *, int, int, const struct timespec *, int *); 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) { static inline bool timespec_iszero(struct timespec __ts) {
return !(__ts.tv_sec | __ts.tv_nsec); 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_sub(struct timeval, struct timeval) pureconst;
struct timeval timeval_subz(struct timeval, struct timeval) pureconst; struct timeval timeval_subz(struct timeval, struct timeval) pureconst;
struct timeval timespec_totimeval(struct timespec) 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) { static inline bool timeval_iszero(struct timeval __tv) {
return !(__tv.tv_sec | __tv.tv_usec); 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; int rc;
struct timespec ts[2]; struct timespec ts[2];
if (tv) { if (tv) {
ts[0].tv_sec = tv[0].tv_sec; ts[0] = timeval_totimespec(tv[0]);
ts[0].tv_nsec = tv[0].tv_usec * 1000; ts[1] = timeval_totimespec(tv[1]);
ts[1].tv_sec = tv[1].tv_sec;
ts[1].tv_nsec = tv[1].tv_usec * 1000;
rc = __utimens(AT_FDCWD, path, ts, 0); rc = __utimens(AT_FDCWD, path, ts, 0);
} else { } else {
rc = __utimens(AT_FDCWD, path, 0, 0); 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 uint64_t fsblkcnt_t;
typedef int64_t fsfilcnt_t; /* uint32_t on xnu */ typedef int64_t fsfilcnt_t; /* uint32_t on xnu */
typedef uint32_t gid_t; 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 uint32_t in_addr_t; typedef uint32_t in_addr_t;
typedef uint16_t in_port_t; typedef uint16_t in_port_t;

View file

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

View file

@ -22,7 +22,7 @@
#include "libc/dns/resolvconf.h" #include "libc/dns/resolvconf.h"
#include "libc/dns/servicestxt.h" #include "libc/dns/servicestxt.h"
#include "libc/fmt/conv.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/gc.h"
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
@ -94,7 +94,7 @@ int getaddrinfo(const char *name, const char *service,
return EAI_NONAME; return EAI_NONAME;
} else if (ResolveHostsTxt(GetHostsTxt(), AF_INET, name, ai->ai_addr, } else if (ResolveHostsTxt(GetHostsTxt(), AF_INET, name, ai->ai_addr,
sizeof(ai->ai_addr4), &canon) > 0) { 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; *res = ai;
return 0; return 0;
} else { } else {

View file

@ -28,7 +28,7 @@
#include "libc/mem/mem.h" #include "libc/mem/mem.h"
#include "libc/sysv/consts/af.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 struct hostent *ptr1, he1;
static char h_name[DNS_NAME_MAX + 1]; static char h_name[DNS_NAME_MAX + 1];
static char *h_aliases[1]; static char *h_aliases[1];

View file

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

View file

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

View file

@ -53,8 +53,8 @@
* *
* @return 0 on success or EAI_xxx value * @return 0 on success or EAI_xxx value
*/ */
int getnameinfo(const struct sockaddr *addr, socklen_t addrlen, char *name, int getnameinfo(const struct sockaddr *addr, uint32_t addrlen, char *name,
socklen_t namelen, char *service, socklen_t servicelen, uint32_t namelen, char *service, uint32_t servicelen,
int flags) { int flags) {
char *p, rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"]; char *p, rdomain[1 + sizeof "255.255.255.255.in-addr.arpa"];
char info[NI_MAXHOST + 1]; 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 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "libc/dce.h"
#include "libc/dns/prototxt.h" #include "libc/dns/prototxt.h"
#include "libc/nt/systeminfo.h" #include "libc/dns/servicestxt.h"
#include "libc/str/str.h"
textwindows char *GetNtProtocolsTxtPath(char *pathbuf, uint32_t size) { const char *GetProtocolsTxtPath(char *buf, size_t size) {
/* protocol, not plural */ if (!IsWindows()) {
const char *const kWinHostsPath = "\\drivers\\etc\\protocol"; return "/etc/protocols";
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];
} else { } 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 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE. OTHER DEALINGS IN THE SOFTWARE.
*/ */
#include "libc/dce.h"
#include "libc/dns/servicestxt.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 *GetServicesTxtPath(char *path, size_t size) {
const char *const kWinHostsPath = "\\drivers\\etc\\services"; if (!IsWindows()) {
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size); return "/etc/services";
if (len && len + strlen(kWinHostsPath) + 1 < size) {
if (pathbuf[len] == '\\') pathbuf[len--] = '\0';
memcpy(&pathbuf[len], kWinHostsPath, strlen(kWinHostsPath) + 1);
return &pathbuf[0];
} else { } else {
return NULL; return GetSystemDirectoryPath(path, size, "drivers\\etc\\services");
} }
} }

View file

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

View file

@ -41,9 +41,12 @@ struct servent *getservbyport(int port, const char *proto) {
ptr1 = &se1; ptr1 = &se1;
} }
if (proto) { if (proto) {
if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) return NULL; if (!memccpy(localproto, proto, '\0', DNS_NAME_MAX)) {
} else return NULL;
strcpy(localproto, ""); }
} else {
*localproto = 0;
}
if (LookupServicesByPort(ntohs(port), ptr1->s_proto, DNS_NAME_MAX, if (LookupServicesByPort(ntohs(port), ptr1->s_proto, DNS_NAME_MAX,
ptr1->s_name, DNS_NAME_MAX, NULL) == -1) { ptr1->s_name, DNS_NAME_MAX, NULL) == -1) {
return NULL; 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) { const char *filepath) {
FILE *f; FILE *f;
char *line; char *line;
const char *path;
size_t linesize; size_t linesize;
const char *path;
int found, result; int found, result;
char pathbuf[PATH_MAX]; char pathbuf[256];
char *name, *number, *alias, *comment, *tok; char *name, *number, *alias, *comment, *tok;
if (!(path = filepath)) { if (!(path = filepath)) {
path = "/etc/protocols"; path =
if (IsWindows()) { !IsWindows()
path = ? "/etc/protocols"
firstnonnull(GetNtProtocolsTxtPath(pathbuf, ARRAYLEN(pathbuf)), path); : firstnonnull(GetProtocolsTxtPath(pathbuf, sizeof(pathbuf)), path);
}
} }
if (bufsize == 0 || !(f = fopen(path, "r"))) { if (bufsize == 0 || !(f = fopen(path, "r"))) {
return -1; return -1;
@ -70,18 +69,20 @@ int LookupProtoByName(const char *protoname, char *buf, size_t bufsize,
linesize = 0; linesize = 0;
found = 0; found = 0;
result = -1; result = -1;
while (found == 0 && (getline(&line, &linesize, f)) != -1) { while (found == 0 && getline(&line, &linesize, f) != -1) {
if ((comment = strchr(line, '#'))) *comment = '\0'; if ((comment = strchr(line, '#'))) *comment = '\0';
name = strtok_r(line, " \t\r\n\v", &tok); name = strtok_r(line, " \t\r\n\v", &tok);
number = strtok_r(NULL, "/ \t\r\n\v", &tok); number = strtok_r(NULL, "/ \t\r\n\v", &tok);
if (name && number) { if (name && number) {
alias = name; alias = name;
while (alias && strcasecmp(alias, protoname) != 0) while (alias && strcasecmp(alias, protoname)) {
alias = strtok_r(NULL, " \t\r\n\v", &tok); 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)) { if (!memccpy(buf, name, '\0', bufsize)) {
strcpy(buf, ""); if (bufsize) {
*buf = 0;
}
break; break;
} }
result = atoi(number); result = atoi(number);

View file

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

View file

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

View file

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

View file

@ -22,7 +22,7 @@
#include "libc/sock/sock.h" #include "libc/sock/sock.h"
#include "libc/sysv/consts/af.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) #define ADDRLEN sizeof(struct sockaddr_in)
struct addrinfo *newaddrinfo(uint16_t port) { struct addrinfo *newaddrinfo(uint16_t port) {

View file

@ -5,11 +5,12 @@
#if !(__ASSEMBLER__ + __LINKER__ + 0) #if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_ COSMOPOLITAN_C_START_
const char *GetProtocolsTxtPath(char *, size_t);
int LookupProtoByNumber(const int, char *, size_t, const char *) int LookupProtoByNumber(const int, char *, size_t, const char *)
paramsnonnull((2)); paramsnonnull((2));
int LookupProtoByName(const char *, char *, size_t, const char *) int LookupProtoByName(const char *, char *, size_t, const char *)
paramsnonnull((1, 2)); paramsnonnull((1, 2));
char *GetNtProtocolsTxtPath(char *, uint32_t);
/* TODO: implement like struct HostsTxt? */ /* 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(); if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
for (i = 0; i < ht->entries.i; ++i) { for (i = 0; i < ht->entries.i; ++i) {
if (READ32LE(ip) == READ32LE(ht->entries.p[i].ip)) { 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; return 1;
} }
} }

View file

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

View file

@ -1,19 +1,7 @@
/* #ifndef COSMOPOLITAN_LIBC_STDCKDINT_H_
* Copyright 2023 Justine Alexandra Roberts Tunney #define COSMOPOLITAN_LIBC_STDCKDINT_H_
* #if !(__ASSEMBLER__ + __LINKER__ + 0)
* Permission to use, copy, modify, and/or distribute this software for /* clang-format off */
* 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.
*/
/** /**
* @fileoverview C23 Checked Arithmetic * @fileoverview C23 Checked Arithmetic
@ -54,16 +42,6 @@
* @version 0.1 (2023-07-22) * @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 #define __STDC_VERSION_STDCKDINT_H__ 202311L
#if ((defined(__llvm__) || \ #if ((defined(__llvm__) || \
@ -81,18 +59,12 @@
typedef signed __ckd_intmax __ckd_intmax_t; typedef signed __ckd_intmax __ckd_intmax_t;
typedef unsigned __ckd_intmax __ckd_uintmax_t; typedef unsigned __ckd_intmax __ckd_uintmax_t;
#ifdef __has_builtin #if (!defined(__STRICT_ANSI__) && \
#define __ckd_has_builtin(x) __has_builtin(x) ((defined(__GNUC__) && __GNUC__ >= 5 && \
#else !defined(__chibicc__) && !defined(__ICC)) || \
#define __ckd_has_builtin(x) 0 (__has_builtin(__builtin_add_overflow) && \
#endif __has_builtin(__builtin_sub_overflow) && \
__has_builtin(__builtin_mul_overflow))))
#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))))
#define ckd_add(res, x, y) __builtin_add_overflow((x), (y), (res)) #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_sub(res, x, y) __builtin_sub_overflow((x), (y), (res))
#define ckd_mul(res, x, y) __builtin_mul_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) #define ckd_mul(res, x, y) (*(res) = (x) * (y), 0)
#endif /* GNU */ #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; f->state = EOF;
if (f->noclose) { if (f->noclose) {
f->fd = -1; f->fd = -1;
} else if (close(f->fd) == -1) { } else if (f->fd != -1 && close(f->fd) == -1) {
f->state = errno; f->state = errno;
} }
if (f->state == EOF) { 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 -*-│ /*-*- 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 2022 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,11 +16,16 @@
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/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) { long double strtold(const char *s, char **endptr) {
return (struct timespec){tv.tv_sec, tv.tv_usec * 1000}; 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; break;
} }
} }
sigaction(SIGINT, &saveint, 0);
sigaction(SIGQUIT, &savequit, 0); sigaction(SIGQUIT, &savequit, 0);
sigaction(SIGINT, &saveint, 0);
} }
sigprocmask(SIG_SETMASK, &savemask, 0); sigprocmask(SIG_SETMASK, &savemask, 0);
ALLOW_CANCELLATIONS; ALLOW_CANCELLATIONS;

View file

@ -46,11 +46,11 @@
* @asyncsignalsafe * @asyncsignalsafe
*/ */
void *memccpy(void *dst, const void *src, int c, size_t n) { void *memccpy(void *dst, const void *src, int c, size_t n) {
char *d;
size_t i; size_t i;
unsigned char *d; const char *s;
const unsigned char *s;
for (d = dst, s = src, i = 0; i < n; ++i) { 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; return d + i + 1;
} }
} }

View file

@ -16,27 +16,30 @@
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/macros.internal.h"
#include "libc/str/str.h" #include "libc/str/str.h"
/** /**
* Prepares static search buffer. * Prepares static search buffer.
* *
* 1. If SRC is too long, it's truncated and *not* NUL-terminated. * 1. If SRC is too long, it's truncated and *not* NUL-terminated.
*
* 2. If SRC is too short, the remainder is zero-filled. * 2. If SRC is too short, the remainder is zero-filled.
* *
* Please note this function isn't designed to prevent untrustworthy * @param dst is output buffer
* data from modifying memory without authorization. Consider trying * @param src is a nul-terminated string
* memccpy() for that purpose. * @param dstlen is size of `dst` buffer
* * @return pointer to first nul-terminator, otherwise dest + stride
* @return dest + stride
* @see stncpy(), memccpy()
* @asyncsignalsafe * @asyncsignalsafe
* @see strncpy()
* @see memccpy()
* @see strlcpy()
*/ */
char *stpncpy(char *dest, const char *src, size_t stride) { char *stpncpy(char *dst, const char *src, size_t dstlen) {
char *p; size_t srclen, cpylen, zerlen;
if ((p = memccpy(dest, src, '\0', stride))) { srclen = strlen(src);
bzero(p, dest + stride - p); cpylen = MIN(srclen, dstlen);
} if (cpylen) memcpy(dst, src, cpylen);
return dest + stride; 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 * @param 𝑛 is maximum number of characters from s to copy
* @return 𝑑 * @return 𝑑
* @note 𝑑 and 𝑠 can't overlap * @note 𝑑 and 𝑠 can't overlap
* @asyncsignaslenafe * @asyncsignalsafe
*/ */
char *strncat(char *d, const char *s, size_t n) { char *strncat(char *d, const char *s, size_t n) {
size_t o; size_t dn, sn;
if (!memccpy(d + (o = strlen(d)), s, '\0', n)) { if ((sn = strnlen(s, n))) {
d[o + n] = '\0'; dn = strlen(d);
memcpy(d + dn, s, sn);
d[dn + sn] = 0;
} }
return d; return d;
} }

View file

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

View file

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

View file

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

View file

@ -19,33 +19,20 @@
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h" #include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/sigset.h" #include "libc/calls/struct/sigset.h"
#include "libc/dce.h"
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#include "libc/sysv/consts/sig.h" #include "libc/sysv/consts/sig.h"
#include "libc/testlib/subprocess.h" #include "libc/testlib/subprocess.h"
#include "libc/testlib/testlib.h" #include "libc/testlib/testlib.h"
TEST(abort, sysv) { TEST(abort, test) {
if (IsWindows()) return;
SPAWN(fork); SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL)); ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
abort(); abort();
TERMS(SIGABRT); TERMS(SIGABRT);
} }
TEST(abort, windows) { TEST(abort, blocked_stillTerminates) {
if (!IsWindows()) return;
SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
abort();
EXITS(128 + SIGABRT);
}
////////////////////////////////////////////////////////////////////////////////
TEST(abort, blocked_stillTerminates_sysv) {
sigset_t ss; sigset_t ss;
if (IsWindows()) return;
SPAWN(fork); SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL)); ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_DFL));
sigfillset(&ss); sigfillset(&ss);
@ -54,52 +41,19 @@ TEST(abort, blocked_stillTerminates_sysv) {
TERMS(SIGABRT); TERMS(SIGABRT);
} }
TEST(abort, blocked_stillTerminates_windows) { TEST(abort, ign_stillTerminates) {
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;
SPAWN(fork); SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN)); ASSERT_NE(SIG_ERR, signal(SIGABRT, SIG_IGN));
abort(); abort();
TERMS(SIGABRT); 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) { void Ignore(int sig) {
} }
TEST(abort, handled_stillTerminates_sysv) { TEST(abort, handled_stillTerminates) {
if (IsWindows()) return;
SPAWN(fork); SPAWN(fork);
ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore)); ASSERT_NE(SIG_ERR, signal(SIGABRT, Ignore));
abort(); abort();
TERMS(SIGABRT); 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 -*-│ /*-*- 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 2022 Justine Alexandra Roberts Tunney Copyright 2023 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the any purpose with or without fee is hereby granted, provided that the
@ -16,24 +16,13 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "libc/thread/thread.h" #include "libc/str/str.h"
#include "third_party/gdtoa/lock.h" #include "libc/testlib/testlib.h"
static pthread_mutex_t __gdtoa_lock_obj; TEST(strncat, test) {
static pthread_mutex_t __gdtoa_lock1_obj; char buf[32] = "foo";
EXPECT_STREQ("foobar", strncat(buf, "bar", 3));
int(__gdtoa_lock)(void) { EXPECT_STREQ("foobarbar", strncat(buf, "bar", 10));
return pthread_mutex_lock(&__gdtoa_lock_obj); EXPECT_STREQ("foobarbarb", strncat(buf, "bar", 1));
} EXPECT_STREQ("foobarbarb", strncat(buf, "", 1));
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);
} }

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/calls/calls.h"
#include "libc/macros.internal.h" #include "libc/macros.internal.h"
#include "libc/runtime/runtime.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/gdtoa.internal.h"
#include "third_party/gdtoa/lock.h"
/* clang-format off */ /* clang-format off */
static ThInfo TI0; 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 static void
__gdtoa_Brelease(Bigint *rv) __gdtoa_Brelease(Bigint *rv)
@ -63,7 +110,11 @@ __gdtoa_Bclear(void)
__attribute__((__constructor__)) static void __attribute__((__constructor__)) static void
__gdtoa_Binit(void) __gdtoa_Binit(void)
{ {
__gdtoa_initlock();
__gdtoa_initlock1();
atexit(__gdtoa_Bclear); atexit(__gdtoa_Bclear);
pthread_atfork(__gdtoa_lock1, __gdtoa_unlock1, __gdtoa_initlock1);
pthread_atfork(__gdtoa_lock, __gdtoa_unlock, __gdtoa_initlock);
} }
static ThInfo * 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/timeval.h"
#include "libc/calls/struct/winsize.h" #include "libc/calls/struct/winsize.h"
#include "libc/calls/ucontext.h" #include "libc/calls/ucontext.h"
#include "libc/calls/weirdtypes.h"
#include "libc/dce.h" #include "libc/dce.h"
#include "libc/dns/dns.h" #include "libc/dns/dns.h"
#include "libc/errno.h" #include "libc/errno.h"

View file

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

View file

@ -97,6 +97,7 @@ void mbedtls_test_platform_teardown(void) {
} }
wontreturn void exit(int rc) { 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); if (rc) xwrite(1, output, appendz(output).i);
free(output); free(output);
output = 0; output = 0;

View file

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