diff --git a/build/definitions.mk b/build/definitions.mk index fc5b9e6f9..2e47ab5fd 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -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),) diff --git a/examples/whois.c b/examples/whois.c index d61fd0f5e..79fafc9d9 100644 --- a/examples/whois.c +++ b/examples/whois.c @@ -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" diff --git a/libc/calls/close.c b/libc/calls/close.c index 4617184e9..541d75348 100644 --- a/libc/calls/close.c +++ b/libc/calls/close.c @@ -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() diff --git a/libc/calls/gethostname-linux.c b/libc/calls/gethostname-linux.c index f92edac32..c27940bf7 100644 --- a/libc/calls/gethostname-linux.c +++ b/libc/calls/gethostname-linux.c @@ -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" diff --git a/libc/calls/getprogramexecutablename.greg.c b/libc/calls/getprogramexecutablename.greg.c index 71a0663a5..064c4c930 100644 --- a/libc/calls/getprogramexecutablename.greg.c +++ b/libc/calls/getprogramexecutablename.greg.c @@ -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; } diff --git a/libc/calls/struct/timespec.h b/libc/calls/struct/timespec.h index a64de9235..c0739941a 100644 --- a/libc/calls/struct/timespec.h +++ b/libc/calls/struct/timespec.h @@ -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); } diff --git a/libc/calls/struct/timeval.h b/libc/calls/struct/timeval.h index af8a599cb..fcc39d0f3 100644 --- a/libc/calls/struct/timeval.h +++ b/libc/calls/struct/timeval.h @@ -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); } diff --git a/libc/calls/utimes.c b/libc/calls/utimes.c index fe4b427ab..2fd5c9edb 100644 --- a/libc/calls/utimes.c +++ b/libc/calls/utimes.c @@ -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); diff --git a/libc/calls/weirdtypes.h b/libc/calls/weirdtypes.h index dfb7424af..c1c911cae 100644 --- a/libc/calls/weirdtypes.h +++ b/libc/calls/weirdtypes.h @@ -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; diff --git a/libc/dns/dns.h b/libc/dns/dns.h index 7e0c7ff46..5c7a4ca08 100644 --- a/libc/dns/dns.h +++ b/libc/dns/dns.h @@ -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(); diff --git a/libc/dns/ent.h b/libc/dns/ent.h index c27f233fd..5c91e48db 100644 --- a/libc/dns/ent.h +++ b/libc/dns/ent.h @@ -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); diff --git a/libc/dns/getaddrinfo.c b/libc/dns/getaddrinfo.c index 1d2427264..c6c56c72e 100644 --- a/libc/dns/getaddrinfo.c +++ b/libc/dns/getaddrinfo.c @@ -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 { diff --git a/libc/dns/gethostbyaddr.c b/libc/dns/gethostbyaddr.c index 1f570f825..c381da7d2 100644 --- a/libc/dns/gethostbyaddr.c +++ b/libc/dns/gethostbyaddr.c @@ -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]; diff --git a/libc/dns/gethostbyname.c b/libc/dns/gethostbyname.c index dd70de244..8e1cf25aa 100644 --- a/libc/dns/gethostbyname.c +++ b/libc/dns/gethostbyname.c @@ -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); diff --git a/libc/dns/gethoststxt.c b/libc/dns/gethoststxt.c index bfa04bf7c..dd172d36b 100644 --- a/libc/dns/gethoststxt.c +++ b/libc/dns/gethoststxt.c @@ -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. */ } diff --git a/libc/dns/getnameinfo.c b/libc/dns/getnameinfo.c index e5120d8f4..c6c15ba36 100644 --- a/libc/dns/getnameinfo.c +++ b/libc/dns/getnameinfo.c @@ -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]; diff --git a/libc/dns/getntprotocolstxtpath.c b/libc/dns/getntprotocolstxtpath.c index b369d3f91..3fb56905a 100644 --- a/libc/dns/getntprotocolstxtpath.c +++ b/libc/dns/getntprotocolstxtpath.c @@ -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"); } } diff --git a/libc/dns/getntservicestxtpath.c b/libc/dns/getntservicestxtpath.c index 21249d111..ce8b45ca7 100644 --- a/libc/dns/getntservicestxtpath.c +++ b/libc/dns/getntservicestxtpath.c @@ -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"); } } diff --git a/libc/dns/getservbyname.c b/libc/dns/getservbyname.c index 293fd528e..b594236b0 100644 --- a/libc/dns/getservbyname.c +++ b/libc/dns/getservbyname.c @@ -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; diff --git a/libc/dns/getservbyport.c b/libc/dns/getservbyport.c index 091674823..abc2312d0 100644 --- a/libc/dns/getservbyport.c +++ b/libc/dns/getservbyport.c @@ -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; diff --git a/libc/dns/getsystemdirectorypath.c b/libc/dns/getsystemdirectorypath.c new file mode 100644 index 000000000..82e9cf281 --- /dev/null +++ b/libc/dns/getsystemdirectorypath.c @@ -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; + } +} diff --git a/libc/dns/lookupprotobyname.c b/libc/dns/lookupprotobyname.c index 099e399b8..7364b3b4b 100644 --- a/libc/dns/lookupprotobyname.c +++ b/libc/dns/lookupprotobyname.c @@ -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); diff --git a/libc/dns/lookupprotobynumber.c b/libc/dns/lookupprotobynumber.c index c1c9235b2..ce37eb0f3 100644 --- a/libc/dns/lookupprotobynumber.c +++ b/libc/dns/lookupprotobynumber.c @@ -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; diff --git a/libc/dns/lookupservicesbyname.c b/libc/dns/lookupservicesbyname.c index b709515ed..25924faa0 100644 --- a/libc/dns/lookupservicesbyname.c +++ b/libc/dns/lookupservicesbyname.c @@ -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); diff --git a/libc/dns/lookupservicesbyport.c b/libc/dns/lookupservicesbyport.c index 5bbf4f1ed..b6f31390a 100644 --- a/libc/dns/lookupservicesbyport.c +++ b/libc/dns/lookupservicesbyport.c @@ -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; diff --git a/libc/dns/newaddrinfo.c b/libc/dns/newaddrinfo.c index 8ee20a5fd..c0e728b55 100644 --- a/libc/dns/newaddrinfo.c +++ b/libc/dns/newaddrinfo.c @@ -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) { diff --git a/libc/dns/prototxt.h b/libc/dns/prototxt.h index 61d19a228..21e15ebe9 100644 --- a/libc/dns/prototxt.h +++ b/libc/dns/prototxt.h @@ -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? */ diff --git a/libc/dns/resolvehostsreverse.c b/libc/dns/resolvehostsreverse.c index 395e73efa..7e8a803a6 100644 --- a/libc/dns/resolvehostsreverse.c +++ b/libc/dns/resolvehostsreverse.c @@ -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; } } diff --git a/libc/dns/servicestxt.h b/libc/dns/servicestxt.h index 2bd39dd28..8e29133fa 100644 --- a/libc/dns/servicestxt.h +++ b/libc/dns/servicestxt.h @@ -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? */ diff --git a/libc/stdckdint.h b/libc/stdckdint.h index c40f9348c..9af1aebd6 100644 --- a/libc/stdckdint.h +++ b/libc/stdckdint.h @@ -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_ */ diff --git a/third_party/gdtoa/atof.c b/libc/stdio/atof.c similarity index 100% rename from third_party/gdtoa/atof.c rename to libc/stdio/atof.c diff --git a/libc/stdio/fclose.c b/libc/stdio/fclose.c index 28131e951..1f2871487 100644 --- a/libc/stdio/fclose.c +++ b/libc/stdio/fclose.c @@ -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) { diff --git a/libc/calls/timeval_totimespec.c b/libc/stdio/strtold.c similarity index 84% rename from libc/calls/timeval_totimespec.c rename to libc/stdio/strtold.c index 16bccc97f..96f85e3a6 100644 --- a/libc/calls/timeval_totimespec.c +++ b/libc/stdio/strtold.c @@ -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); diff --git a/libc/stdio/system.c b/libc/stdio/system.c index bc55a7995..c340d5eda 100644 --- a/libc/stdio/system.c +++ b/libc/stdio/system.c @@ -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; diff --git a/third_party/gdtoa/wcstod.c b/libc/stdio/wcstod.c similarity index 100% rename from third_party/gdtoa/wcstod.c rename to libc/stdio/wcstod.c diff --git a/third_party/gdtoa/wcstof.c b/libc/stdio/wcstof.c similarity index 100% rename from third_party/gdtoa/wcstof.c rename to libc/stdio/wcstof.c diff --git a/third_party/gdtoa/wcstold.c b/libc/stdio/wcstold.c similarity index 100% rename from third_party/gdtoa/wcstold.c rename to libc/stdio/wcstold.c diff --git a/libc/str/memccpy.c b/libc/str/memccpy.c index 1988140b7..294e441b0 100644 --- a/libc/str/memccpy.c +++ b/libc/str/memccpy.c @@ -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; } } diff --git a/libc/str/stpncpy.c b/libc/str/stpncpy.c index cb9f78da2..c24b8ac4c 100644 --- a/libc/str/stpncpy.c +++ b/libc/str/stpncpy.c @@ -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; } diff --git a/libc/str/strncat.c b/libc/str/strncat.c index 5215c9671..5b5f1d560 100644 --- a/libc/str/strncat.c +++ b/libc/str/strncat.c @@ -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; } diff --git a/libc/str/strncpy.c b/libc/str/strncpy.c index e867280e6..5948abf41 100644 --- a/libc/str/strncpy.c +++ b/libc/str/strncpy.c @@ -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; } diff --git a/test/libc/calls/raise_test.c b/test/libc/calls/raise_test.c index 0d7b36a78..b85932370 100644 --- a/test/libc/calls/raise_test.c +++ b/test/libc/calls/raise_test.c @@ -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) { diff --git a/test/libc/dns/servicestxt_test.c b/test/libc/dns/servicestxt_test.c index bd12510e3..a3e08c095 100644 --- a/test/libc/dns/servicestxt_test.c +++ b/test/libc/dns/servicestxt_test.c @@ -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; diff --git a/test/libc/runtime/abort_test.c b/test/libc/runtime/abort_test.c index 3924c5a24..4d88b90c9 100644 --- a/test/libc/runtime/abort_test.c +++ b/test/libc/runtime/abort_test.c @@ -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); -} diff --git a/third_party/gdtoa/lock.c b/test/libc/str/strncat_test.c similarity index 76% rename from third_party/gdtoa/lock.c rename to test/libc/str/strncat_test.c index 6297114c7..61f1573f0 100644 --- a/third_party/gdtoa/lock.c +++ b/test/libc/str/strncat_test.c @@ -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)); } diff --git a/third_party/gdtoa/lock.h b/third_party/gdtoa/lock.h deleted file mode 100644 index 107bc3358..000000000 --- a/third_party/gdtoa/lock.h +++ /dev/null @@ -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_ */ diff --git a/third_party/gdtoa/misc.c b/third_party/gdtoa/misc.c index 4976bd02a..ffcd7071f 100644 --- a/third_party/gdtoa/misc.c +++ b/third_party/gdtoa/misc.c @@ -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 * diff --git a/third_party/gdtoa/strtold.c b/third_party/gdtoa/strtold.c deleted file mode 100644 index 410d2beb2..000000000 --- a/third_party/gdtoa/strtold.c +++ /dev/null @@ -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 │ -│ or Justine Tunney │ -│ │ -│ 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); diff --git a/third_party/lua/lunix.c b/third_party/lua/lunix.c index 9d485d016..1ff267441 100644 --- a/third_party/lua/lunix.c +++ b/third_party/lua/lunix.c @@ -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" diff --git a/third_party/mbedtls/net_sockets.c b/third_party/mbedtls/net_sockets.c index 4e958986e..68dc8a240 100644 --- a/third_party/mbedtls/net_sockets.c +++ b/third_party/mbedtls/net_sockets.c @@ -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) diff --git a/third_party/mbedtls/test/lib.c b/third_party/mbedtls/test/lib.c index d3ae618ab..cd67cfb3a 100644 --- a/third_party/mbedtls/test/lib.c +++ b/third_party/mbedtls/test/lib.c @@ -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; diff --git a/tool/build/runitd.c b/tool/build/runitd.c index d2dd9b5da..c56342209 100644 --- a/tool/build/runitd.c +++ b/tool/build/runitd.c @@ -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