diff options
Diffstat (limited to 'src/libposixplz')
-rw-r--r-- | src/libposixplz/doublefork.c | 51 | ||||
-rw-r--r-- | src/libposixplz/execvep.c | 39 | ||||
-rw-r--r-- | src/libposixplz/getpeereid.c | 66 | ||||
-rw-r--r-- | src/libposixplz/memmem.c | 187 | ||||
-rw-r--r-- | src/libposixplz/setgroups.c | 50 | ||||
-rw-r--r-- | src/libposixplz/strnlen.c | 16 | ||||
-rw-r--r-- | src/libposixplz/touch.c | 56 |
7 files changed, 465 insertions, 0 deletions
diff --git a/src/libposixplz/doublefork.c b/src/libposixplz/doublefork.c new file mode 100644 index 0000000..6038a9f --- /dev/null +++ b/src/libposixplz/doublefork.c @@ -0,0 +1,51 @@ +/* ISC license. */ + +#include <sys/wait.h> +#include <unistd.h> +#include <errno.h> +#include <skalibs/uint64.h> +#include <skalibs/allreadwrite.h> +#include <skalibs/djbunix.h> +#include <skalibs/posixplz.h> + +pid_t doublefork () +{ + char pack[8] ; + int fd[2] ; + pid_t child ; + if (pipe(fd) == -1) return -1 ; + child = fork() ; + switch (child) + { + case -1: + { + fd_close(fd[1]) ; + fd_close(fd[0]) ; + return -1 ; + } + case 0: + { + pid_t pid ; + fd_close(fd[0]) ; + pid = fork() ; + switch (pid) + { + case -1: _exit(errno) ; + case 0: fd_close(fd[1]) ; return 0 ; + } + uint64_pack_big(pack, pid) ; + _exit((allwrite(fd[1], pack, 8) < 8) ? errno : 0) ; + } + } + fd_close(fd[1]) ; + { + uint64_t grandchild = 0 ; + int wstat ; + if (allread(fd[0], pack, 8) < 8) grandchild = 1 ; + fd_close(fd[0]) ; + wait_pid(child, &wstat) ; + if (grandchild) return (errno = WIFSIGNALED(wstat) ? EINTR : WEXITSTATUS(wstat), -1) ; + uint64_unpack_big(pack, &grandchild) ; + return (pid_t)grandchild ; + } +} diff --git a/src/libposixplz/execvep.c b/src/libposixplz/execvep.c new file mode 100644 index 0000000..acdf11f --- /dev/null +++ b/src/libposixplz/execvep.c @@ -0,0 +1,39 @@ +/* ISC license. */ + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <skalibs/bytestr.h> +#include <skalibs/posixplz.h> + +void execvep (char const *file, char const *const *argv, char const *const *envp, char const *path) +{ + if (!path) errno = EINVAL ; + else if (file[str_chr(file, '/')]) + execve(file, (char *const *)argv, (char *const *)envp) ; /* execve prototype sucks */ + else + { + size_t pathlen = strlen(path) + 1 ; + size_t filelen = strlen(file) ; + int savederrno = 0 ; + while (pathlen) + { + size_t split = byte_chr(path, pathlen - 1, ':') ; + if (split) + { + char tmp[split + 2 + filelen] ; + memcpy(tmp, path, split) ; + tmp[split] = '/' ; + memcpy(tmp + split + 1, file, filelen + 1) ; + execve(tmp, (char *const *)argv, (char *const *)envp) ; + if (errno != ENOENT) + { + savederrno = errno ; + if ((errno != EACCES) && (errno != EPERM) && (errno != EISDIR)) break ; + } + } + path += split+1 ; pathlen -= split+1 ; + } + if (savederrno) errno = savederrno ; + } +} diff --git a/src/libposixplz/getpeereid.c b/src/libposixplz/getpeereid.c new file mode 100644 index 0000000..ae1142f --- /dev/null +++ b/src/libposixplz/getpeereid.c @@ -0,0 +1,66 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASGETPEEREID +/* syscall exists - do nothing */ + +#else + +#ifdef SKALIBS_HASSOPEERCRED +/* implementation with SO_PEERCRED */ + +#include <skalibs/nonposix.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <skalibs/posixplz.h> + +int getpeereid (int s, uid_t *u, gid_t *g) +{ + struct ucred blah ; + socklen_t len = sizeof(blah) ; + + if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &blah, &len) == -1) + return -1 ; + *u = blah.uid ; + *g = blah.gid ; + return 0 ; +} + +#else + +#ifdef SKALIBS_HASGETPEERUCRED +/* implementation with getpeerucred() */ + +#include <skalibs/nonposix.h> +#include <ucred.h> +#include <skalibs/posixplz.h> + +int getpeereid (int s, uid_t *u, gid_t *g) +{ + ucred_t *cred ; + if (getpeerucred(s, &cred) == -1) return -1 ; + *u = ucred_geteuid(cred) ; + *g = ucred_getegid(cred) ; + ucred_free(cred) ; + return 0 ; +} + +#else + +/* can't find a real implementation, make a stub */ + +#include <errno.h> +#include <skalibs/posixplz.h> + +int getpeereid (int s, uid_t *uid, gid_t *gid) +{ + (void)s ; + *uid = *gid = -1 ; + errno = ENOSYS ; + return -1 ; +} + +#endif +#endif +#endif diff --git a/src/libposixplz/memmem.c b/src/libposixplz/memmem.c new file mode 100644 index 0000000..d107346 --- /dev/null +++ b/src/libposixplz/memmem.c @@ -0,0 +1,187 @@ +/* MIT license. See below. */ + +#include <skalibs/sysdeps.h> + +#ifndef SKALIBS_HASMEMMEM + +/* + If the underlying platform does not provide memmem(), then the + following implementation is used. It comes from the musl libc, + which is MIT-licensed: + +---------------------------------------------------------------------- +Copyright © 2005-2017 Rich Felker, Szabolcs Nagy, Timo Teräs, Alexander Monakov + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +---------------------------------------------------------------------- + +*/ + +#include <string.h> +#include <stdint.h> +#include <skalibs/posixplz.h> + +static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; + for (h+=2, k-=2; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-2; + return hw == nw ? (char *)h-2 : 0; +} + +static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; + for (h+=3, k-=3; k; k--, hw = (hw|*h++)<<8) + if (hw == nw) return (char *)h-3; + return hw == nw ? (char *)h-3 : 0; +} + +static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; + for (h+=4, k-=4; k; k--, hw = hw<<8 | *h++) + if (hw == nw) return (char *)h-4; + return hw == nw ? (char *)h-4 : 0; +} + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BITOP(a,b,op) \ + ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) + +static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l) +{ + size_t i, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (i=0; i<l; i++) + BITOP(byteset, n[i], |=), shift[n[i]] = i+1; + + /* Compute maximal suffix */ + ip = -1; jp = 0; k = p = 1; + while (jp+k<l) { + if (n[ip+k] == n[jp+k]) { + if (k == p) { + jp += p; + k = 1; + } else k++; + } else if (n[ip+k] > n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k<l) { + if (n[ip+k] == n[jp+k]) { + if (k == p) { + jp += p; + k = 1; + } else k++; + } else if (n[ip+k] < n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + if (ip+1 > ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (memcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Search loop */ + for (;;) { + /* If remainder of haystack is shorter than needle, done */ + if (z-h < l) return 0; + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l-1], &)) { + k = l-shift[h[l-1]]; + if (k) { + if (mem0 && mem && k < p) k = l-p; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); k<l && n[k] == h[k]; k++); + if (k < l) { + h += k-ms; + mem = 0; + continue; + } + /* Compare left half */ + for (k=ms+1; k>mem && n[k-1] == h[k-1]; k--); + if (k <= mem) return (char *)h; + h += p; + mem = mem0; + } +} + +void *memmem(const void *h0, size_t k, const void *n0, size_t l) +{ + const unsigned char *h = h0, *n = n0; + + /* Return immediately on empty needle */ + if (!l) return (void *)h; + + /* Return immediately when needle is longer than haystack */ + if (k<l) return 0; + + /* Use faster algorithms for short needles */ + h = memchr(h0, *n, k); + if (!h || l==1) return (void *)h; + k -= h - (const unsigned char *)h0; + if (k<l) return 0; + if (l==2) return twobyte_memmem(h, k, n); + if (l==3) return threebyte_memmem(h, k, n); + if (l==4) return fourbyte_memmem(h, k, n); + + return twoway_memmem(h, h+k, n, l); +} + +#endif diff --git a/src/libposixplz/setgroups.c b/src/libposixplz/setgroups.c new file mode 100644 index 0000000..d064ed2 --- /dev/null +++ b/src/libposixplz/setgroups.c @@ -0,0 +1,50 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASSETGROUPS + +#include <skalibs/nonposix.h> +#include <string.h> +#include <unistd.h> +#include <grp.h> +#include <skalibs/setgroups.h> + +int setgroups_and_gid (gid_t g, size_t n, gid_t const *tab) +{ + size_t i = 1 ; + if (!n) return setgroups(1, &g) ; + if (tab[0] == g) return setgroups(n, tab) ; + for (; i < n ; i++) if (tab[i] == g) break ; + if (i < n) + { + gid_t newtab[n] ; + newtab[0] = g ; + memcpy(newtab + 1, tab, i * sizeof(gid_t)) ; + memcpy(newtab + i + 1, tab + i + 1, (n - i - 1) * sizeof(gid_t)) ; + return setgroups(n, newtab) ; + } + else + { + gid_t newtab[n+1] ; + newtab[0] = g ; + memcpy(newtab + 1, tab, n * sizeof(gid_t)) ; + return setgroups(n+1, newtab) ; + } +} + +int setgroups_with_egid (size_t n, gid_t const *tab) +{ + return setgroups_and_gid(getegid(), n, tab) ; +} + +int skalibs_setgroups (size_t n, gid_t const *tab) +{ +#ifdef SKALIBS_BSD_SUCKS + return setgroups_with_egid(n, tab) ; +#else + return setgroups(n, tab) ; +#endif +} + +#endif diff --git a/src/libposixplz/strnlen.c b/src/libposixplz/strnlen.c new file mode 100644 index 0000000..1699771 --- /dev/null +++ b/src/libposixplz/strnlen.c @@ -0,0 +1,16 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifndef SKALIBS_HASSTRNLEN + +#include <string.h> +#include <skalibs/bytestr.h> +#include <skalibs/posixplz.h> + +size_t strnlen (char const *s, size_t max) +{ + return byte_chr(s, max, 0) ; +} + +#endif diff --git a/src/libposixplz/touch.c b/src/libposixplz/touch.c new file mode 100644 index 0000000..c4419ec --- /dev/null +++ b/src/libposixplz/touch.c @@ -0,0 +1,56 @@ +/* ISC license. */ + +#include <skalibs/sysdeps.h> + +#ifdef SKALIBS_HASFUTIMENS + +#include <skalibs/nonposix.h> +#include <time.h> +#include <sys/stat.h> +#include <skalibs/djbunix.h> +#include <skalibs/posixplz.h> + +int touch (char const *file) +{ + int r ; + int fd = open_create(file) ; + if (fd < 0) return 0 ; + r = futimens(fd, 0) >= 0 ; + fd_close(fd) ; + return r ; +} + +#else +#ifdef SKALIBS_HASFUTIMES + +#include <skalibs/nonposix.h> +#include <sys/time.h> +#include <skalibs/djbunix.h> +#include <skalibs/posixplz.h> + +int touch (char const *file) +{ + int r ; + int fd = open_create(file) ; + if (fd < 0) return 0 ; + r = futimes(fd, 0) >= 0 ; + fd_close(fd) ; + return r ; +} + +#else + +#include <sys/time.h> +#include <skalibs/djbunix.h> +#include <skalibs/posixplz.h> + +int touch (char const *file) +{ + int fd = open_create(file) ; + if (fd < 0) return 0 ; + fd_close(fd) ; + return utimes(file, 0) >= 0 ; +} + +#endif +#endif |