summaryrefslogtreecommitdiffstats
path: root/libc-top-half/musl/src/misc
diff options
context:
space:
mode:
Diffstat (limited to 'libc-top-half/musl/src/misc')
-rw-r--r--libc-top-half/musl/src/misc/a64l.c29
-rw-r--r--libc-top-half/musl/src/misc/basename.c14
-rw-r--r--libc-top-half/musl/src/misc/dirname.c14
-rw-r--r--libc-top-half/musl/src/misc/ffs.c7
-rw-r--r--libc-top-half/musl/src/misc/ffsl.c7
-rw-r--r--libc-top-half/musl/src/misc/ffsll.c7
-rw-r--r--libc-top-half/musl/src/misc/fmtmsg.c96
-rw-r--r--libc-top-half/musl/src/misc/forkpty.c57
-rw-r--r--libc-top-half/musl/src/misc/get_current_dir_name.c15
-rw-r--r--libc-top-half/musl/src/misc/getauxval.c15
-rw-r--r--libc-top-half/musl/src/misc/getdomainname.c17
-rw-r--r--libc-top-half/musl/src/misc/getentropy.c33
-rw-r--r--libc-top-half/musl/src/misc/gethostid.c6
-rw-r--r--libc-top-half/musl/src/misc/getopt.c105
-rw-r--r--libc-top-half/musl/src/misc/getopt_long.c148
-rw-r--r--libc-top-half/musl/src/misc/getpriority.c9
-rw-r--r--libc-top-half/musl/src/misc/getresgid.c8
-rw-r--r--libc-top-half/musl/src/misc/getresuid.c8
-rw-r--r--libc-top-half/musl/src/misc/getrlimit.c26
-rw-r--r--libc-top-half/musl/src/misc/getrusage.c35
-rw-r--r--libc-top-half/musl/src/misc/getsubopt.c23
-rw-r--r--libc-top-half/musl/src/misc/initgroups.c11
-rw-r--r--libc-top-half/musl/src/misc/ioctl.c151
-rw-r--r--libc-top-half/musl/src/misc/issetugid.c8
-rw-r--r--libc-top-half/musl/src/misc/lockf.c32
-rw-r--r--libc-top-half/musl/src/misc/login_tty.c14
-rw-r--r--libc-top-half/musl/src/misc/mntent.c77
-rw-r--r--libc-top-half/musl/src/misc/nftw.c148
-rw-r--r--libc-top-half/musl/src/misc/openpty.c40
-rw-r--r--libc-top-half/musl/src/misc/ptsname.c13
-rw-r--r--libc-top-half/musl/src/misc/pty.c35
-rw-r--r--libc-top-half/musl/src/misc/realpath.c156
-rw-r--r--libc-top-half/musl/src/misc/setdomainname.c8
-rw-r--r--libc-top-half/musl/src/misc/setpriority.c7
-rw-r--r--libc-top-half/musl/src/misc/setrlimit.c47
-rw-r--r--libc-top-half/musl/src/misc/syscall.c21
-rw-r--r--libc-top-half/musl/src/misc/syslog.c162
-rw-r--r--libc-top-half/musl/src/misc/uname.c32
-rw-r--r--libc-top-half/musl/src/misc/wordexp.c187
39 files changed, 1828 insertions, 0 deletions
diff --git a/libc-top-half/musl/src/misc/a64l.c b/libc-top-half/musl/src/misc/a64l.c
new file mode 100644
index 0000000..6055771
--- /dev/null
+++ b/libc-top-half/musl/src/misc/a64l.c
@@ -0,0 +1,29 @@
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+static const char digits[] =
+ "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+long a64l(const char *s)
+{
+ int e;
+ uint32_t x = 0;
+ for (e=0; e<36 && *s; e+=6, s++) {
+ const char *d = strchr(digits, *s);
+ if (!d) break;
+ x |= (uint32_t)(d-digits)<<e;
+ }
+ return (int32_t)x;
+}
+
+char *l64a(long x0)
+{
+ static char s[7];
+ char *p;
+ uint32_t x = x0;
+ for (p=s; x; p++, x>>=6)
+ *p = digits[x&63];
+ *p = 0;
+ return s;
+}
diff --git a/libc-top-half/musl/src/misc/basename.c b/libc-top-half/musl/src/misc/basename.c
new file mode 100644
index 0000000..438377b
--- /dev/null
+++ b/libc-top-half/musl/src/misc/basename.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#include <libgen.h>
+
+char *basename(char *s)
+{
+ size_t i;
+ if (!s || !*s) return ".";
+ i = strlen(s)-1;
+ for (; i&&s[i]=='/'; i--) s[i] = 0;
+ for (; i&&s[i-1]!='/'; i--);
+ return s+i;
+}
+
+weak_alias(basename, __xpg_basename);
diff --git a/libc-top-half/musl/src/misc/dirname.c b/libc-top-half/musl/src/misc/dirname.c
new file mode 100644
index 0000000..dd57088
--- /dev/null
+++ b/libc-top-half/musl/src/misc/dirname.c
@@ -0,0 +1,14 @@
+#include <string.h>
+#include <libgen.h>
+
+char *dirname(char *s)
+{
+ size_t i;
+ if (!s || !*s) return ".";
+ i = strlen(s)-1;
+ for (; s[i]=='/'; i--) if (!i) return "/";
+ for (; s[i]!='/'; i--) if (!i) return ".";
+ for (; s[i]=='/'; i--) if (!i) return "/";
+ s[i+1] = 0;
+ return s;
+}
diff --git a/libc-top-half/musl/src/misc/ffs.c b/libc-top-half/musl/src/misc/ffs.c
new file mode 100644
index 0000000..673ce5a
--- /dev/null
+++ b/libc-top-half/musl/src/misc/ffs.c
@@ -0,0 +1,7 @@
+#include <strings.h>
+#include "atomic.h"
+
+int ffs(int i)
+{
+ return i ? a_ctz_l(i)+1 : 0;
+}
diff --git a/libc-top-half/musl/src/misc/ffsl.c b/libc-top-half/musl/src/misc/ffsl.c
new file mode 100644
index 0000000..0105c66
--- /dev/null
+++ b/libc-top-half/musl/src/misc/ffsl.c
@@ -0,0 +1,7 @@
+#include <strings.h>
+#include "atomic.h"
+
+int ffsl(long i)
+{
+ return i ? a_ctz_l(i)+1 : 0;
+}
diff --git a/libc-top-half/musl/src/misc/ffsll.c b/libc-top-half/musl/src/misc/ffsll.c
new file mode 100644
index 0000000..0c5ced8
--- /dev/null
+++ b/libc-top-half/musl/src/misc/ffsll.c
@@ -0,0 +1,7 @@
+#include <strings.h>
+#include "atomic.h"
+
+int ffsll(long long i)
+{
+ return i ? a_ctz_64(i)+1 : 0;
+}
diff --git a/libc-top-half/musl/src/misc/fmtmsg.c b/libc-top-half/musl/src/misc/fmtmsg.c
new file mode 100644
index 0000000..0c66076
--- /dev/null
+++ b/libc-top-half/musl/src/misc/fmtmsg.c
@@ -0,0 +1,96 @@
+/* Public domain fmtmsg()
+ * Written by Isaac Dunham, 2014
+ */
+#include <fmtmsg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+#include <pthread.h>
+#endif
+
+/*
+ * If lstr is the first part of bstr, check that the next char in bstr
+ * is either \0 or :
+ */
+static int _strcolcmp(const char *lstr, const char *bstr)
+{
+ size_t i = 0;
+ while (lstr[i] && bstr[i] && (bstr[i] == lstr[i])) i++;
+ if ( lstr[i] || (bstr[i] && bstr[i] != ':')) return 1;
+ return 0;
+}
+
+int fmtmsg(long classification, const char *label, int severity,
+ const char *text, const char *action, const char *tag)
+{
+ int ret = 0, i, consolefd, verb = 0;
+ char *errstring = MM_NULLSEV, *cmsg = getenv("MSGVERB");
+ char *const msgs[] = {
+ "label", "severity", "text", "action", "tag", NULL
+ };
+ int cs;
+
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+#endif
+
+ if (severity == MM_HALT) errstring = "HALT: ";
+ else if (severity == MM_ERROR) errstring = "ERROR: ";
+ else if (severity == MM_WARNING) errstring = "WARNING: ";
+ else if (severity == MM_INFO) errstring = "INFO: ";
+
+ if (classification & MM_CONSOLE) {
+ consolefd = open("/dev/console", O_WRONLY);
+ if (consolefd < 0) {
+ ret = MM_NOCON;
+ } else {
+ if (dprintf(consolefd, "%s%s%s%s%s%s%s%s\n",
+ label?label:"", label?": ":"",
+ severity?errstring:"", text?text:"",
+ action?"\nTO FIX: ":"",
+ action?action:"", action?" ":"",
+ tag?tag:"" )<1)
+ ret = MM_NOCON;
+ close(consolefd);
+ }
+ }
+
+ if (classification & MM_PRINT) {
+ while (cmsg && cmsg[0]) {
+ for(i=0; msgs[i]; i++) {
+ if (!_strcolcmp(msgs[i], cmsg)) break;
+ }
+ if (msgs[i] == NULL) {
+ //ignore MSGVERB-unrecognized component
+ verb = 0xFF;
+ break;
+ } else {
+ verb |= (1 << i);
+ cmsg = strchr(cmsg, ':');
+ if (cmsg) cmsg++;
+ }
+ }
+ if (!verb) verb = 0xFF;
+ if (dprintf(2, "%s%s%s%s%s%s%s%s\n",
+ (verb&1 && label) ? label : "",
+ (verb&1 && label) ? ": " : "",
+ (verb&2 && severity) ? errstring : "",
+ (verb&4 && text) ? text : "",
+ (verb&8 && action) ? "\nTO FIX: " : "",
+ (verb&8 && action) ? action : "",
+ (verb&8 && action) ? " " : "",
+ (verb&16 && tag) ? tag : "" ) < 1)
+ ret |= MM_NOMSG;
+ }
+ if ((ret & (MM_NOCON|MM_NOMSG)) == (MM_NOCON|MM_NOMSG))
+ ret = MM_NOTOK;
+
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(cs, 0);
+#endif
+
+ return ret;
+}
diff --git a/libc-top-half/musl/src/misc/forkpty.c b/libc-top-half/musl/src/misc/forkpty.c
new file mode 100644
index 0000000..caf13ad
--- /dev/null
+++ b/libc-top-half/musl/src/misc/forkpty.c
@@ -0,0 +1,57 @@
+#include <pty.h>
+#include <utmp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <pthread.h>
+
+int forkpty(int *pm, char *name, const struct termios *tio, const struct winsize *ws)
+{
+ int m, s, ec=0, p[2], cs;
+ pid_t pid=-1;
+ sigset_t set, oldset;
+
+ if (openpty(&m, &s, name, tio, ws) < 0) return -1;
+
+ sigfillset(&set);
+ pthread_sigmask(SIG_BLOCK, &set, &oldset);
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+
+ if (pipe2(p, O_CLOEXEC)) {
+ close(s);
+ goto out;
+ }
+
+ pid = fork();
+ if (!pid) {
+ close(m);
+ close(p[0]);
+ if (login_tty(s)) {
+ write(p[1], &errno, sizeof errno);
+ _exit(127);
+ }
+ close(p[1]);
+ pthread_setcancelstate(cs, 0);
+ pthread_sigmask(SIG_SETMASK, &oldset, 0);
+ return 0;
+ }
+ close(s);
+ close(p[1]);
+ if (read(p[0], &ec, sizeof ec) > 0) {
+ int status;
+ waitpid(pid, &status, 0);
+ pid = -1;
+ errno = ec;
+ }
+ close(p[0]);
+
+out:
+ if (pid > 0) *pm = m;
+ else close(m);
+
+ pthread_setcancelstate(cs, 0);
+ pthread_sigmask(SIG_SETMASK, &oldset, 0);
+
+ return pid;
+}
diff --git a/libc-top-half/musl/src/misc/get_current_dir_name.c b/libc-top-half/musl/src/misc/get_current_dir_name.c
new file mode 100644
index 0000000..782cddc
--- /dev/null
+++ b/libc-top-half/musl/src/misc/get_current_dir_name.c
@@ -0,0 +1,15 @@
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+char *get_current_dir_name(void) {
+ struct stat a, b;
+ char *res = getenv("PWD");
+ if (res && *res && !stat(res, &a) && !stat(".", &b)
+ && (a.st_dev == b.st_dev) && (a.st_ino == b.st_ino))
+ return strdup(res);
+ return getcwd(0, 0);
+}
diff --git a/libc-top-half/musl/src/misc/getauxval.c b/libc-top-half/musl/src/misc/getauxval.c
new file mode 100644
index 0000000..57f21ee
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getauxval.c
@@ -0,0 +1,15 @@
+#include <sys/auxv.h>
+#include <errno.h>
+#include "libc.h"
+
+unsigned long __getauxval(unsigned long item)
+{
+ size_t *auxv = libc.auxv;
+ if (item == AT_SECURE) return libc.secure;
+ for (; *auxv; auxv+=2)
+ if (*auxv==item) return auxv[1];
+ errno = ENOENT;
+ return 0;
+}
+
+weak_alias(__getauxval, getauxval);
diff --git a/libc-top-half/musl/src/misc/getdomainname.c b/libc-top-half/musl/src/misc/getdomainname.c
new file mode 100644
index 0000000..59df566
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getdomainname.c
@@ -0,0 +1,17 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <string.h>
+#include <errno.h>
+
+int getdomainname(char *name, size_t len)
+{
+ struct utsname temp;
+ uname(&temp);
+ if (!len || strlen(temp.domainname) >= len) {
+ errno = EINVAL;
+ return -1;
+ }
+ strcpy(name, temp.domainname);
+ return 0;
+}
diff --git a/libc-top-half/musl/src/misc/getentropy.c b/libc-top-half/musl/src/misc/getentropy.c
new file mode 100644
index 0000000..651ea95
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getentropy.c
@@ -0,0 +1,33 @@
+#define _BSD_SOURCE
+#include <unistd.h>
+#include <sys/random.h>
+#include <pthread.h>
+#include <errno.h>
+
+int getentropy(void *buffer, size_t len)
+{
+ int cs, ret = 0;
+ char *pos = buffer;
+
+ if (len > 256) {
+ errno = EIO;
+ return -1;
+ }
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+
+ while (len) {
+ ret = getrandom(pos, len, 0);
+ if (ret < 0) {
+ if (errno == EINTR) continue;
+ else break;
+ }
+ pos += ret;
+ len -= ret;
+ ret = 0;
+ }
+
+ pthread_setcancelstate(cs, 0);
+
+ return ret;
+}
diff --git a/libc-top-half/musl/src/misc/gethostid.c b/libc-top-half/musl/src/misc/gethostid.c
new file mode 100644
index 0000000..25bb35d
--- /dev/null
+++ b/libc-top-half/musl/src/misc/gethostid.c
@@ -0,0 +1,6 @@
+#include <unistd.h>
+
+long gethostid()
+{
+ return 0;
+}
diff --git a/libc-top-half/musl/src/misc/getopt.c b/libc-top-half/musl/src/misc/getopt.c
new file mode 100644
index 0000000..c3f6699
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getopt.c
@@ -0,0 +1,105 @@
+#define _BSD_SOURCE
+#include <unistd.h>
+#include <wchar.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include "locale_impl.h"
+#include "stdio_impl.h"
+
+char *optarg;
+int optind=1, opterr=1, optopt, __optpos, __optreset=0;
+
+#define optpos __optpos
+weak_alias(__optreset, optreset);
+
+void __getopt_msg(const char *a, const char *b, const char *c, size_t l)
+{
+ FILE *f = stderr;
+ b = __lctrans_cur(b);
+ FLOCK(f);
+ fputs(a, f)>=0
+ && fwrite(b, strlen(b), 1, f)
+ && fwrite(c, 1, l, f)==l
+ && putc('\n', f);
+ FUNLOCK(f);
+}
+
+int getopt(int argc, char * const argv[], const char *optstring)
+{
+ int i;
+ wchar_t c, d;
+ int k, l;
+ char *optchar;
+
+ if (!optind || __optreset) {
+ __optreset = 0;
+ __optpos = 0;
+ optind = 1;
+ }
+
+ if (optind >= argc || !argv[optind])
+ return -1;
+
+ if (argv[optind][0] != '-') {
+ if (optstring[0] == '-') {
+ optarg = argv[optind++];
+ return 1;
+ }
+ return -1;
+ }
+
+ if (!argv[optind][1])
+ return -1;
+
+ if (argv[optind][1] == '-' && !argv[optind][2])
+ return optind++, -1;
+
+ if (!optpos) optpos++;
+ if ((k = mbtowc(&c, argv[optind]+optpos, MB_LEN_MAX)) < 0) {
+ k = 1;
+ c = 0xfffd; /* replacement char */
+ }
+ optchar = argv[optind]+optpos;
+ optpos += k;
+
+ if (!argv[optind][optpos]) {
+ optind++;
+ optpos = 0;
+ }
+
+ if (optstring[0] == '-' || optstring[0] == '+')
+ optstring++;
+
+ i = 0;
+ d = 0;
+ do {
+ l = mbtowc(&d, optstring+i, MB_LEN_MAX);
+ if (l>0) i+=l; else i++;
+ } while (l && d != c);
+
+ if (d != c || c == ':') {
+ optopt = c;
+ if (optstring[0] != ':' && opterr)
+ __getopt_msg(argv[0], ": unrecognized option: ", optchar, k);
+ return '?';
+ }
+ if (optstring[i] == ':') {
+ optarg = 0;
+ if (optstring[i+1] != ':' || optpos) {
+ optarg = argv[optind++] + optpos;
+ optpos = 0;
+ }
+ if (optind > argc) {
+ optopt = c;
+ if (optstring[0] == ':') return ':';
+ if (opterr) __getopt_msg(argv[0],
+ ": option requires an argument: ",
+ optchar, k);
+ return '?';
+ }
+ }
+ return c;
+}
+
+weak_alias(getopt, __posix_getopt);
diff --git a/libc-top-half/musl/src/misc/getopt_long.c b/libc-top-half/musl/src/misc/getopt_long.c
new file mode 100644
index 0000000..6949ab1
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getopt_long.c
@@ -0,0 +1,148 @@
+#define _GNU_SOURCE
+#include <stddef.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <string.h>
+#include "stdio_impl.h"
+
+extern int __optpos, __optreset;
+
+static void permute(char *const *argv, int dest, int src)
+{
+ char **av = (char **)argv;
+ char *tmp = av[src];
+ int i;
+ for (i=src; i>dest; i--)
+ av[i] = av[i-1];
+ av[dest] = tmp;
+}
+
+static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly);
+
+static int __getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
+{
+ int ret, skipped, resumed;
+ if (!optind || __optreset) {
+ __optreset = 0;
+ __optpos = 0;
+ optind = 1;
+ }
+ if (optind >= argc || !argv[optind]) return -1;
+ skipped = optind;
+ if (optstring[0] != '+' && optstring[0] != '-') {
+ int i;
+ for (i=optind; ; i++) {
+ if (i >= argc || !argv[i]) return -1;
+ if (argv[i][0] == '-' && argv[i][1]) break;
+ }
+ optind = i;
+ }
+ resumed = optind;
+ ret = __getopt_long_core(argc, argv, optstring, longopts, idx, longonly);
+ if (resumed > skipped) {
+ int i, cnt = optind-resumed;
+ for (i=0; i<cnt; i++)
+ permute(argv, skipped, optind-1);
+ optind = skipped + cnt;
+ }
+ return ret;
+}
+
+static int __getopt_long_core(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx, int longonly)
+{
+ optarg = 0;
+ if (longopts && argv[optind][0] == '-' &&
+ ((longonly && argv[optind][1] && argv[optind][1] != '-') ||
+ (argv[optind][1] == '-' && argv[optind][2])))
+ {
+ int colon = optstring[optstring[0]=='+'||optstring[0]=='-']==':';
+ int i, cnt, match;
+ char *arg, *opt, *start = argv[optind]+1;
+ for (cnt=i=0; longopts[i].name; i++) {
+ const char *name = longopts[i].name;
+ opt = start;
+ if (*opt == '-') opt++;
+ while (*opt && *opt != '=' && *opt == *name)
+ name++, opt++;
+ if (*opt && *opt != '=') continue;
+ arg = opt;
+ match = i;
+ if (!*name) {
+ cnt = 1;
+ break;
+ }
+ cnt++;
+ }
+ if (cnt==1 && longonly && arg-start == mblen(start, MB_LEN_MAX)) {
+ int l = arg-start;
+ for (i=0; optstring[i]; i++) {
+ int j;
+ for (j=0; j<l && start[j]==optstring[i+j]; j++);
+ if (j==l) {
+ cnt++;
+ break;
+ }
+ }
+ }
+ if (cnt==1) {
+ i = match;
+ opt = arg;
+ optind++;
+ if (*opt == '=') {
+ if (!longopts[i].has_arg) {
+ optopt = longopts[i].val;
+ if (colon || !opterr)
+ return '?';
+ __getopt_msg(argv[0],
+ ": option does not take an argument: ",
+ longopts[i].name,
+ strlen(longopts[i].name));
+ return '?';
+ }
+ optarg = opt+1;
+ } else if (longopts[i].has_arg == required_argument) {
+ if (!(optarg = argv[optind])) {
+ optopt = longopts[i].val;
+ if (colon) return ':';
+ if (!opterr) return '?';
+ __getopt_msg(argv[0],
+ ": option requires an argument: ",
+ longopts[i].name,
+ strlen(longopts[i].name));
+ return '?';
+ }
+ optind++;
+ }
+ if (idx) *idx = i;
+ if (longopts[i].flag) {
+ *longopts[i].flag = longopts[i].val;
+ return 0;
+ }
+ return longopts[i].val;
+ }
+ if (argv[optind][1] == '-') {
+ optopt = 0;
+ if (!colon && opterr)
+ __getopt_msg(argv[0], cnt ?
+ ": option is ambiguous: " :
+ ": unrecognized option: ",
+ argv[optind]+2,
+ strlen(argv[optind]+2));
+ optind++;
+ return '?';
+ }
+ }
+ return getopt(argc, argv, optstring);
+}
+
+int getopt_long(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
+{
+ return __getopt_long(argc, argv, optstring, longopts, idx, 0);
+}
+
+int getopt_long_only(int argc, char *const *argv, const char *optstring, const struct option *longopts, int *idx)
+{
+ return __getopt_long(argc, argv, optstring, longopts, idx, 1);
+}
diff --git a/libc-top-half/musl/src/misc/getpriority.c b/libc-top-half/musl/src/misc/getpriority.c
new file mode 100644
index 0000000..5c0b168
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getpriority.c
@@ -0,0 +1,9 @@
+#include <sys/resource.h>
+#include "syscall.h"
+
+int getpriority(int which, id_t who)
+{
+ int ret = syscall(SYS_getpriority, which, who);
+ if (ret < 0) return ret;
+ return 20-ret;
+}
diff --git a/libc-top-half/musl/src/misc/getresgid.c b/libc-top-half/musl/src/misc/getresgid.c
new file mode 100644
index 0000000..d00d9a9
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getresgid.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include "syscall.h"
+
+int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
+{
+ return syscall(SYS_getresgid, rgid, egid, sgid);
+}
diff --git a/libc-top-half/musl/src/misc/getresuid.c b/libc-top-half/musl/src/misc/getresuid.c
new file mode 100644
index 0000000..d75d5d4
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getresuid.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include "syscall.h"
+
+int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
+{
+ return syscall(SYS_getresuid, ruid, euid, suid);
+}
diff --git a/libc-top-half/musl/src/misc/getrlimit.c b/libc-top-half/musl/src/misc/getrlimit.c
new file mode 100644
index 0000000..2ab2f0f
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getrlimit.c
@@ -0,0 +1,26 @@
+#include <sys/resource.h>
+#include <errno.h>
+#include "syscall.h"
+
+#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
+
+int getrlimit(int resource, struct rlimit *rlim)
+{
+ unsigned long k_rlim[2];
+ int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
+ if (!ret) {
+ FIX(rlim->rlim_cur);
+ FIX(rlim->rlim_max);
+ }
+ if (!ret || errno != ENOSYS)
+ return ret;
+ if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
+ return -1;
+ rlim->rlim_cur = k_rlim[0] == -1UL ? RLIM_INFINITY : k_rlim[0];
+ rlim->rlim_max = k_rlim[1] == -1UL ? RLIM_INFINITY : k_rlim[1];
+ FIX(rlim->rlim_cur);
+ FIX(rlim->rlim_max);
+ return 0;
+}
+
+weak_alias(getrlimit, getrlimit64);
diff --git a/libc-top-half/musl/src/misc/getrusage.c b/libc-top-half/musl/src/misc/getrusage.c
new file mode 100644
index 0000000..8e03e2e
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getrusage.c
@@ -0,0 +1,35 @@
+#include <sys/resource.h>
+#include <string.h>
+#include <errno.h>
+#include "syscall.h"
+
+int getrusage(int who, struct rusage *ru)
+{
+ int r;
+#ifdef SYS_getrusage_time64
+ long long kru64[18];
+ r = __syscall(SYS_getrusage_time64, who, kru64);
+ if (!r) {
+ ru->ru_utime = (struct timeval)
+ { .tv_sec = kru64[0], .tv_usec = kru64[1] };
+ ru->ru_stime = (struct timeval)
+ { .tv_sec = kru64[2], .tv_usec = kru64[3] };
+ char *slots = (char *)&ru->ru_maxrss;
+ for (int i=0; i<14; i++)
+ *(long *)(slots + i*sizeof(long)) = kru64[4+i];
+ }
+ if (SYS_getrusage_time64 == SYS_getrusage || r != -ENOSYS)
+ return __syscall_ret(r);
+#endif
+ char *dest = (char *)&ru->ru_maxrss - 4*sizeof(long);
+ r = __syscall(SYS_getrusage, who, dest);
+ if (!r && sizeof(time_t) > sizeof(long)) {
+ long kru[4];
+ memcpy(kru, dest, 4*sizeof(long));
+ ru->ru_utime = (struct timeval)
+ { .tv_sec = kru[0], .tv_usec = kru[1] };
+ ru->ru_stime = (struct timeval)
+ { .tv_sec = kru[2], .tv_usec = kru[3] };
+ }
+ return __syscall_ret(r);
+}
diff --git a/libc-top-half/musl/src/misc/getsubopt.c b/libc-top-half/musl/src/misc/getsubopt.c
new file mode 100644
index 0000000..53ee957
--- /dev/null
+++ b/libc-top-half/musl/src/misc/getsubopt.c
@@ -0,0 +1,23 @@
+#include <stdlib.h>
+#include <string.h>
+
+int getsubopt(char **opt, char *const *keys, char **val)
+{
+ char *s = *opt;
+ int i;
+
+ *val = NULL;
+ *opt = strchr(s, ',');
+ if (*opt) *(*opt)++ = 0;
+ else *opt = s + strlen(s);
+
+ for (i=0; keys[i]; i++) {
+ size_t l = strlen(keys[i]);
+ if (strncmp(keys[i], s, l)) continue;
+ if (s[l] == '=')
+ *val = s + l + 1;
+ else if (s[l]) continue;
+ return i;
+ }
+ return -1;
+}
diff --git a/libc-top-half/musl/src/misc/initgroups.c b/libc-top-half/musl/src/misc/initgroups.c
new file mode 100644
index 0000000..922a958
--- /dev/null
+++ b/libc-top-half/musl/src/misc/initgroups.c
@@ -0,0 +1,11 @@
+#define _GNU_SOURCE
+#include <grp.h>
+#include <limits.h>
+
+int initgroups(const char *user, gid_t gid)
+{
+ gid_t groups[NGROUPS_MAX];
+ int count = NGROUPS_MAX;
+ if (getgrouplist(user, gid, groups, &count) < 0) return -1;
+ return setgroups(count, groups);
+}
diff --git a/libc-top-half/musl/src/misc/ioctl.c b/libc-top-half/musl/src/misc/ioctl.c
new file mode 100644
index 0000000..35804f0
--- /dev/null
+++ b/libc-top-half/musl/src/misc/ioctl.c
@@ -0,0 +1,151 @@
+#include <sys/ioctl.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/time.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <endian.h>
+#include "syscall.h"
+
+#define alignof(t) offsetof(struct { char c; t x; }, x)
+
+#define W 1
+#define R 2
+#define WR 3
+
+struct ioctl_compat_map {
+ int new_req, old_req;
+ unsigned char old_size, dir, force_align, noffs;
+ unsigned char offsets[8];
+};
+
+#define NINTH(a,b,c,d,e,f,g,h,i,...) i
+#define COUNT(...) NINTH(__VA_ARGS__,8,7,6,5,4,3,2,1,0)
+#define OFFS(...) COUNT(__VA_ARGS__), { __VA_ARGS__ }
+
+/* yields a type for a struct with original size n, with a misaligned
+ * timeval/timespec expanded from 32- to 64-bit. for use with ioctl
+ * number producing macros; only size of result is meaningful. */
+#define new_misaligned(n) struct { int i; time_t t; char c[(n)-4]; }
+
+struct v4l2_event {
+ uint32_t a;
+ uint64_t b[8];
+ uint32_t c[2], ts[2], d[9];
+};
+
+static const struct ioctl_compat_map compat_map[] = {
+ { SIOCGSTAMP, SIOCGSTAMP_OLD, 8, R, 0, OFFS(0, 4) },
+ { SIOCGSTAMPNS, SIOCGSTAMPNS_OLD, 8, R, 0, OFFS(0, 4) },
+
+ /* SNDRV_TIMER_IOCTL_STATUS */
+ { _IOR('T', 0x14, char[96]), _IOR('T', 0x14, 88), 88, R, 0, OFFS(0,4) },
+
+ /* SNDRV_PCM_IOCTL_STATUS[_EXT] */
+ { _IOR('A', 0x20, char[128]), _IOR('A', 0x20, char[108]), 108, R, 1, OFFS(4,8,12,16,52,56,60,64) },
+ { _IOWR('A', 0x24, char[128]), _IOWR('A', 0x24, char[108]), 108, WR, 1, OFFS(4,8,12,16,52,56,60,64) },
+
+ /* SNDRV_RAWMIDI_IOCTL_STATUS */
+ { _IOWR('W', 0x20, char[48]), _IOWR('W', 0x20, char[36]), 36, WR, 1, OFFS(4,8) },
+
+ /* SNDRV_PCM_IOCTL_SYNC_PTR - with 3 subtables */
+ { _IOWR('A', 0x23, char[136]), _IOWR('A', 0x23, char[132]), 0, WR, 1, 0 },
+ { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_sync_ptr (flags only) */
+ { 0, 0, 32, WR, 1, OFFS(8,12,16,24,28) }, /* snd_pcm_mmap_status */
+ { 0, 0, 4, WR, 1, 0 }, /* snd_pcm_mmap_control (each member) */
+
+ /* VIDIOC_QUERYBUF, VIDIOC_QBUF, VIDIOC_DQBUF, VIDIOC_PREPARE_BUF */
+ { _IOWR('V', 9, new_misaligned(68)), _IOWR('V', 9, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 15, new_misaligned(68)), _IOWR('V', 15, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 17, new_misaligned(68)), _IOWR('V', 17, char[68]), 68, WR, 1, OFFS(20, 24) },
+ { _IOWR('V', 93, new_misaligned(68)), _IOWR('V', 93, char[68]), 68, WR, 1, OFFS(20, 24) },
+
+ /* VIDIOC_DQEVENT */
+ { _IOR('V', 89, new_misaligned(120)), _IOR('V', 89, struct v4l2_event), sizeof(struct v4l2_event),
+ R, 0, OFFS(offsetof(struct v4l2_event, ts[0]), offsetof(struct v4l2_event, ts[1])) },
+
+ /* VIDIOC_OMAP3ISP_STAT_REQ */
+ { _IOWR('V', 192+6, char[32]), _IOWR('V', 192+6, char[24]), 22, WR, 0, OFFS(0,4) },
+
+ /* PPPIOCGIDLE */
+ { _IOR('t', 63, char[16]), _IOR('t', 63, char[8]), 8, R, 0, OFFS(0,4) },
+
+ /* PPGETTIME, PPSETTIME */
+ { _IOR('p', 0x95, char[16]), _IOR('p', 0x95, char[8]), 8, R, 0, OFFS(0,4) },
+ { _IOW('p', 0x96, char[16]), _IOW('p', 0x96, char[8]), 8, W, 0, OFFS(0,4) },
+
+ /* LPSETTIMEOUT */
+ { _IOW(0x6, 0xf, char[16]), 0x060f, 8, W, 0, OFFS(0,4) },
+};
+
+static void convert_ioctl_struct(const struct ioctl_compat_map *map, char *old, char *new, int dir)
+{
+ int new_offset = 0;
+ int old_offset = 0;
+ int old_size = map->old_size;
+ if (!(dir & map->dir)) return;
+ if (!map->old_size) {
+ /* offsets hard-coded for SNDRV_PCM_IOCTL_SYNC_PTR;
+ * if another exception appears this needs changing. */
+ convert_ioctl_struct(map+1, old, new, dir);
+ convert_ioctl_struct(map+2, old+4, new+8, dir);
+ /* snd_pcm_mmap_control, special-cased due to kernel
+ * type definition having been botched. */
+ int adj = BYTE_ORDER==BIG_ENDIAN ? 4 : 0;
+ convert_ioctl_struct(map+3, old+68, new+72+adj, dir);
+ convert_ioctl_struct(map+3, old+72, new+76+3*adj, dir);
+ return;
+ }
+ for (int i=0; i < map->noffs; i++) {
+ int ts_offset = map->offsets[i];
+ int len = ts_offset-old_offset;
+ if (dir==W) memcpy(old+old_offset, new+new_offset, len);
+ else memcpy(new+new_offset, old+old_offset, len);
+ new_offset += len;
+ old_offset += len;
+ long long new_ts;
+ long old_ts;
+ int align = map->force_align ? sizeof(time_t) : alignof(time_t);
+ new_offset += (align-1) & -new_offset;
+ if (dir==W) {
+ memcpy(&new_ts, new+new_offset, sizeof new_ts);
+ old_ts = new_ts;
+ memcpy(old+old_offset, &old_ts, sizeof old_ts);
+ } else {
+ memcpy(&old_ts, old+old_offset, sizeof old_ts);
+ new_ts = old_ts;
+ memcpy(new+new_offset, &new_ts, sizeof new_ts);
+ }
+ new_offset += sizeof new_ts;
+ old_offset += sizeof old_ts;
+ }
+ if (dir==W) memcpy(old+old_offset, new+new_offset, old_size-old_offset);
+ else memcpy(new+new_offset, old+old_offset, old_size-old_offset);
+}
+
+int ioctl(int fd, int req, ...)
+{
+ void *arg;
+ va_list ap;
+ va_start(ap, req);
+ arg = va_arg(ap, void *);
+ va_end(ap);
+ int r = __syscall(SYS_ioctl, fd, req, arg);
+ if (SIOCGSTAMP != SIOCGSTAMP_OLD && req && r==-ENOTTY) {
+ for (int i=0; i<sizeof compat_map/sizeof *compat_map; i++) {
+ if (compat_map[i].new_req != req) continue;
+ union {
+ long long align;
+ char buf[256];
+ } u;
+ convert_ioctl_struct(&compat_map[i], u.buf, arg, W);
+ r = __syscall(SYS_ioctl, fd, compat_map[i].old_req, u.buf);
+ if (r<0) break;
+ convert_ioctl_struct(&compat_map[i], u.buf, arg, R);
+ break;
+ }
+ }
+ return __syscall_ret(r);
+}
diff --git a/libc-top-half/musl/src/misc/issetugid.c b/libc-top-half/musl/src/misc/issetugid.c
new file mode 100644
index 0000000..ddc2ca0
--- /dev/null
+++ b/libc-top-half/musl/src/misc/issetugid.c
@@ -0,0 +1,8 @@
+#define _BSD_SOURCE
+#include <unistd.h>
+#include "libc.h"
+
+int issetugid(void)
+{
+ return libc.secure;
+}
diff --git a/libc-top-half/musl/src/misc/lockf.c b/libc-top-half/musl/src/misc/lockf.c
new file mode 100644
index 0000000..16a80be
--- /dev/null
+++ b/libc-top-half/musl/src/misc/lockf.c
@@ -0,0 +1,32 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+int lockf(int fd, int op, off_t size)
+{
+ struct flock l = {
+ .l_type = F_WRLCK,
+ .l_whence = SEEK_CUR,
+ .l_len = size,
+ };
+ switch (op) {
+ case F_TEST:
+ l.l_type = F_RDLCK;
+ if (fcntl(fd, F_GETLK, &l) < 0)
+ return -1;
+ if (l.l_type == F_UNLCK || l.l_pid == getpid())
+ return 0;
+ errno = EACCES;
+ return -1;
+ case F_ULOCK:
+ l.l_type = F_UNLCK;
+ case F_TLOCK:
+ return fcntl(fd, F_SETLK, &l);
+ case F_LOCK:
+ return fcntl(fd, F_SETLKW, &l);
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+weak_alias(lockf, lockf64);
diff --git a/libc-top-half/musl/src/misc/login_tty.c b/libc-top-half/musl/src/misc/login_tty.c
new file mode 100644
index 0000000..f0be0a0
--- /dev/null
+++ b/libc-top-half/musl/src/misc/login_tty.c
@@ -0,0 +1,14 @@
+#include <utmp.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+int login_tty(int fd)
+{
+ setsid();
+ if (ioctl(fd, TIOCSCTTY, (char *)0)) return -1;
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+ if (fd>2) close(fd);
+ return 0;
+}
diff --git a/libc-top-half/musl/src/misc/mntent.c b/libc-top-half/musl/src/misc/mntent.c
new file mode 100644
index 0000000..eabb820
--- /dev/null
+++ b/libc-top-half/musl/src/misc/mntent.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h>
+#include <errno.h>
+
+static char *internal_buf;
+static size_t internal_bufsize;
+
+#define SENTINEL (char *)&internal_buf
+
+FILE *setmntent(const char *name, const char *mode)
+{
+ return fopen(name, mode);
+}
+
+int endmntent(FILE *f)
+{
+ if (f) fclose(f);
+ return 1;
+}
+
+struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
+{
+ int cnt, n[8], use_internal = (linebuf == SENTINEL);
+
+ mnt->mnt_freq = 0;
+ mnt->mnt_passno = 0;
+
+ do {
+ if (use_internal) {
+ getline(&internal_buf, &internal_bufsize, f);
+ linebuf = internal_buf;
+ } else {
+ fgets(linebuf, buflen, f);
+ }
+ if (feof(f) || ferror(f)) return 0;
+ if (!strchr(linebuf, '\n')) {
+ fscanf(f, "%*[^\n]%*[\n]");
+ errno = ERANGE;
+ return 0;
+ }
+ cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+ n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
+ &mnt->mnt_freq, &mnt->mnt_passno);
+ } while (cnt < 2 || linebuf[n[0]] == '#');
+
+ linebuf[n[1]] = 0;
+ linebuf[n[3]] = 0;
+ linebuf[n[5]] = 0;
+ linebuf[n[7]] = 0;
+
+ mnt->mnt_fsname = linebuf+n[0];
+ mnt->mnt_dir = linebuf+n[2];
+ mnt->mnt_type = linebuf+n[4];
+ mnt->mnt_opts = linebuf+n[6];
+
+ return mnt;
+}
+
+struct mntent *getmntent(FILE *f)
+{
+ static struct mntent mnt;
+ return getmntent_r(f, &mnt, SENTINEL, 0);
+}
+
+int addmntent(FILE *f, const struct mntent *mnt)
+{
+ if (fseek(f, 0, SEEK_END)) return 1;
+ return fprintf(f, "%s\t%s\t%s\t%s\t%d\t%d\n",
+ mnt->mnt_fsname, mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts,
+ mnt->mnt_freq, mnt->mnt_passno) < 0;
+}
+
+char *hasmntopt(const struct mntent *mnt, const char *opt)
+{
+ return strstr(mnt->mnt_opts, opt);
+}
diff --git a/libc-top-half/musl/src/misc/nftw.c b/libc-top-half/musl/src/misc/nftw.c
new file mode 100644
index 0000000..ebfd615
--- /dev/null
+++ b/libc-top-half/musl/src/misc/nftw.c
@@ -0,0 +1,148 @@
+#include <ftw.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <limits.h>
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+#include <pthread.h>
+#endif
+
+struct history
+{
+ struct history *chain;
+ dev_t dev;
+ ino_t ino;
+ int level;
+ int base;
+};
+
+#undef dirfd
+#define dirfd(d) (*(int *)d)
+
+static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags, struct history *h)
+{
+ size_t l = strlen(path), j = l && path[l-1]=='/' ? l-1 : l;
+ struct stat st;
+ struct history new;
+ int type;
+ int r;
+ int dfd;
+ int err;
+ struct FTW lev;
+
+ if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
+ if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
+ type = FTW_SLN;
+ else if (errno != EACCES) return -1;
+ else type = FTW_NS;
+ } else if (S_ISDIR(st.st_mode)) {
+ if (flags & FTW_DEPTH) type = FTW_DP;
+ else type = FTW_D;
+ } else if (S_ISLNK(st.st_mode)) {
+ if (flags & FTW_PHYS) type = FTW_SL;
+ else type = FTW_SLN;
+ } else {
+ type = FTW_F;
+ }
+
+ if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
+ return 0;
+
+ new.chain = h;
+ new.dev = st.st_dev;
+ new.ino = st.st_ino;
+ new.level = h ? h->level+1 : 0;
+ new.base = j+1;
+
+ lev.level = new.level;
+ if (h) {
+ lev.base = h->base;
+ } else {
+ size_t k;
+ for (k=j; k && path[k]=='/'; k--);
+ for (; k && path[k-1]!='/'; k--);
+ lev.base = k;
+ }
+
+ if (type == FTW_D || type == FTW_DP) {
+ dfd = open(path, O_RDONLY);
+ err = errno;
+ if (dfd < 0 && err == EACCES) type = FTW_DNR;
+ if (!fd_limit) close(dfd);
+ }
+
+ if (!(flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+ return r;
+
+ for (; h; h = h->chain)
+ if (h->dev == st.st_dev && h->ino == st.st_ino)
+ return 0;
+
+ if ((type == FTW_D || type == FTW_DP) && fd_limit) {
+ if (dfd < 0) {
+ errno = err;
+ return -1;
+ }
+ DIR *d = fdopendir(dfd);
+ if (d) {
+ struct dirent *de;
+ while ((de = readdir(d))) {
+ if (de->d_name[0] == '.'
+ && (!de->d_name[1]
+ || (de->d_name[1]=='.'
+ && !de->d_name[2]))) continue;
+ if (strlen(de->d_name) >= PATH_MAX-l) {
+ errno = ENAMETOOLONG;
+ closedir(d);
+ return -1;
+ }
+ path[j]='/';
+ strcpy(path+j+1, de->d_name);
+ if ((r=do_nftw(path, fn, fd_limit-1, flags, &new))) {
+ closedir(d);
+ return r;
+ }
+ }
+ closedir(d);
+ } else {
+ close(dfd);
+ return -1;
+ }
+ }
+
+ path[l] = 0;
+ if ((flags & FTW_DEPTH) && (r=fn(path, &st, type, &lev)))
+ return r;
+
+ return 0;
+}
+
+int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int fd_limit, int flags)
+{
+ int r, cs;
+ size_t l;
+ char pathbuf[PATH_MAX+1];
+
+ if (fd_limit <= 0) return 0;
+
+ l = strlen(path);
+ if (l > PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ memcpy(pathbuf, path, l+1);
+
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+#endif
+ r = do_nftw(pathbuf, fn, fd_limit, flags, NULL);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(cs, 0);
+#endif
+ return r;
+}
+
+weak_alias(nftw, nftw64);
diff --git a/libc-top-half/musl/src/misc/openpty.c b/libc-top-half/musl/src/misc/openpty.c
new file mode 100644
index 0000000..c107406
--- /dev/null
+++ b/libc-top-half/musl/src/misc/openpty.c
@@ -0,0 +1,40 @@
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pty.h>
+#include <stdio.h>
+#include <pthread.h>
+
+/* Nonstandard, but vastly superior to the standard functions */
+
+int openpty(int *pm, int *ps, char *name, const struct termios *tio, const struct winsize *ws)
+{
+ int m, s, n=0, cs;
+ char buf[20];
+
+ m = open("/dev/ptmx", O_RDWR|O_NOCTTY);
+ if (m < 0) return -1;
+
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+
+ if (ioctl(m, TIOCSPTLCK, &n) || ioctl (m, TIOCGPTN, &n))
+ goto fail;
+
+ if (!name) name = buf;
+ snprintf(name, sizeof buf, "/dev/pts/%d", n);
+ if ((s = open(name, O_RDWR|O_NOCTTY)) < 0)
+ goto fail;
+
+ if (tio) tcsetattr(s, TCSANOW, tio);
+ if (ws) ioctl(s, TIOCSWINSZ, ws);
+
+ *pm = m;
+ *ps = s;
+
+ pthread_setcancelstate(cs, 0);
+ return 0;
+fail:
+ close(m);
+ pthread_setcancelstate(cs, 0);
+ return -1;
+}
diff --git a/libc-top-half/musl/src/misc/ptsname.c b/libc-top-half/musl/src/misc/ptsname.c
new file mode 100644
index 0000000..58c151c
--- /dev/null
+++ b/libc-top-half/musl/src/misc/ptsname.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include <errno.h>
+
+char *ptsname(int fd)
+{
+ static char buf[9 + sizeof(int)*3 + 1];
+ int err = __ptsname_r(fd, buf, sizeof buf);
+ if (err) {
+ errno = err;
+ return 0;
+ }
+ return buf;
+}
diff --git a/libc-top-half/musl/src/misc/pty.c b/libc-top-half/musl/src/misc/pty.c
new file mode 100644
index 0000000..a057714
--- /dev/null
+++ b/libc-top-half/musl/src/misc/pty.c
@@ -0,0 +1,35 @@
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include "syscall.h"
+
+int posix_openpt(int flags)
+{
+ int r = open("/dev/ptmx", flags);
+ if (r < 0 && errno == ENOSPC) errno = EAGAIN;
+ return r;
+}
+
+int grantpt(int fd)
+{
+ return 0;
+}
+
+int unlockpt(int fd)
+{
+ int unlock = 0;
+ return ioctl(fd, TIOCSPTLCK, &unlock);
+}
+
+int __ptsname_r(int fd, char *buf, size_t len)
+{
+ int pty, err;
+ if (!buf) len = 0;
+ if ((err = __syscall(SYS_ioctl, fd, TIOCGPTN, &pty))) return -err;
+ if (snprintf(buf, len, "/dev/pts/%d", pty) >= len) return ERANGE;
+ return 0;
+}
+
+weak_alias(__ptsname_r, ptsname_r);
diff --git a/libc-top-half/musl/src/misc/realpath.c b/libc-top-half/musl/src/misc/realpath.c
new file mode 100644
index 0000000..db8b74d
--- /dev/null
+++ b/libc-top-half/musl/src/misc/realpath.c
@@ -0,0 +1,156 @@
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+
+static size_t slash_len(const char *s)
+{
+ const char *s0 = s;
+ while (*s == '/') s++;
+ return s-s0;
+}
+
+char *realpath(const char *restrict filename, char *restrict resolved)
+{
+ char stack[PATH_MAX+1];
+ char output[PATH_MAX];
+ size_t p, q, l, l0, cnt=0, nup=0;
+ int check_dir=0;
+
+ if (!filename) {
+ errno = EINVAL;
+ return 0;
+ }
+ l = strnlen(filename, sizeof stack);
+ if (!l) {
+ errno = ENOENT;
+ return 0;
+ }
+ if (l >= PATH_MAX) goto toolong;
+ p = sizeof stack - l - 1;
+ q = 0;
+ memcpy(stack+p, filename, l+1);
+
+ /* Main loop. Each iteration pops the next part from stack of
+ * remaining path components and consumes any slashes that follow.
+ * If not a link, it's moved to output; if a link, contents are
+ * pushed to the stack. */
+restart:
+ for (; ; p+=slash_len(stack+p)) {
+ /* If stack starts with /, the whole component is / or //
+ * and the output state must be reset. */
+ if (stack[p] == '/') {
+ check_dir=0;
+ nup=0;
+ q=0;
+ output[q++] = '/';
+ p++;
+ /* Initial // is special. */
+ if (stack[p] == '/' && stack[p+1] != '/')
+ output[q++] = '/';
+ continue;
+ }
+
+ char *z = __strchrnul(stack+p, '/');
+ l0 = l = z-(stack+p);
+
+ if (!l && !check_dir) break;
+
+ /* Skip any . component but preserve check_dir status. */
+ if (l==1 && stack[p]=='.') {
+ p += l;
+ continue;
+ }
+
+ /* Copy next component onto output at least temporarily, to
+ * call readlink, but wait to advance output position until
+ * determining it's not a link. */
+ if (q && output[q-1] != '/') {
+ if (!p) goto toolong;
+ stack[--p] = '/';
+ l++;
+ }
+ if (q+l >= PATH_MAX) goto toolong;
+ memcpy(output+q, stack+p, l);
+ output[q+l] = 0;
+ p += l;
+
+ int up = 0;
+ if (l0==2 && stack[p-2]=='.' && stack[p-1]=='.') {
+ up = 1;
+ /* Any non-.. path components we could cancel start
+ * after nup repetitions of the 3-byte string "../";
+ * if there are none, accumulate .. components to
+ * later apply to cwd, if needed. */
+ if (q <= 3*nup) {
+ nup++;
+ q += l;
+ continue;
+ }
+ /* When previous components are already known to be
+ * directories, processing .. can skip readlink. */
+ if (!check_dir) goto skip_readlink;
+ }
+ ssize_t k = readlink(output, stack, p);
+ if (k==p) goto toolong;
+ if (!k) {
+ errno = ENOENT;
+ return 0;
+ }
+ if (k<0) {
+ if (errno != EINVAL) return 0;
+skip_readlink:
+ check_dir = 0;
+ if (up) {
+ while(q && output[q-1]!='/') q--;
+ if (q>1 && (q>2 || output[0]!='/')) q--;
+ continue;
+ }
+ if (l0) q += l;
+ check_dir = stack[p];
+ continue;
+ }
+ if (++cnt == SYMLOOP_MAX) {
+ errno = ELOOP;
+ return 0;
+ }
+
+ /* If link contents end in /, strip any slashes already on
+ * stack to avoid /->// or //->/// or spurious toolong. */
+ if (stack[k-1]=='/') while (stack[p]=='/') p++;
+ p -= k;
+ memmove(stack+p, stack, k);
+
+ /* Skip the stack advancement in case we have a new
+ * absolute base path. */
+ goto restart;
+ }
+
+ output[q] = 0;
+
+ if (output[0] != '/') {
+ if (!getcwd(stack, sizeof stack)) return 0;
+ l = strlen(stack);
+ /* Cancel any initial .. components. */
+ p = 0;
+ while (nup--) {
+ while(l>1 && stack[l-1]!='/') l--;
+ if (l>1) l--;
+ p += 2;
+ if (p<q) p++;
+ }
+ if (q-p && stack[l-1]!='/') stack[l++] = '/';
+ if (l + (q-p) + 1 >= PATH_MAX) goto toolong;
+ memmove(output + l, output + p, q - p + 1);
+ memcpy(output, stack, l);
+ q = l + q-p;
+ }
+
+ if (resolved) return memcpy(resolved, output, q+1);
+ else return strdup(output);
+
+toolong:
+ errno = ENAMETOOLONG;
+ return 0;
+}
diff --git a/libc-top-half/musl/src/misc/setdomainname.c b/libc-top-half/musl/src/misc/setdomainname.c
new file mode 100644
index 0000000..22d3f74
--- /dev/null
+++ b/libc-top-half/musl/src/misc/setdomainname.c
@@ -0,0 +1,8 @@
+#define _GNU_SOURCE
+#include <unistd.h>
+#include "syscall.h"
+
+int setdomainname(const char *name, size_t len)
+{
+ return syscall(SYS_setdomainname, name, len);
+}
diff --git a/libc-top-half/musl/src/misc/setpriority.c b/libc-top-half/musl/src/misc/setpriority.c
new file mode 100644
index 0000000..3098cdf
--- /dev/null
+++ b/libc-top-half/musl/src/misc/setpriority.c
@@ -0,0 +1,7 @@
+#include <sys/resource.h>
+#include "syscall.h"
+
+int setpriority(int which, id_t who, int prio)
+{
+ return syscall(SYS_setpriority, which, who, prio);
+}
diff --git a/libc-top-half/musl/src/misc/setrlimit.c b/libc-top-half/musl/src/misc/setrlimit.c
new file mode 100644
index 0000000..8340aee
--- /dev/null
+++ b/libc-top-half/musl/src/misc/setrlimit.c
@@ -0,0 +1,47 @@
+#include <sys/resource.h>
+#include <errno.h>
+#include "syscall.h"
+#include "libc.h"
+
+#define MIN(a, b) ((a)<(b) ? (a) : (b))
+#define FIX(x) do{ if ((x)>=SYSCALL_RLIM_INFINITY) (x)=RLIM_INFINITY; }while(0)
+
+struct ctx {
+ unsigned long lim[2];
+ int res;
+ int err;
+};
+
+static void do_setrlimit(void *p)
+{
+ struct ctx *c = p;
+ if (c->err>0) return;
+ c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
+}
+
+int setrlimit(int resource, const struct rlimit *rlim)
+{
+ struct rlimit tmp;
+ if (SYSCALL_RLIM_INFINITY != RLIM_INFINITY) {
+ tmp = *rlim;
+ FIX(tmp.rlim_cur);
+ FIX(tmp.rlim_max);
+ rlim = &tmp;
+ }
+ int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
+ if (ret != -ENOSYS) return __syscall_ret(ret);
+
+ struct ctx c = {
+ .lim[0] = MIN(rlim->rlim_cur, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+ .lim[1] = MIN(rlim->rlim_max, MIN(-1UL, SYSCALL_RLIM_INFINITY)),
+ .res = resource, .err = -1
+ };
+ __synccall(do_setrlimit, &c);
+ if (c.err) {
+ if (c.err>0) errno = c.err;
+ return -1;
+ }
+ return 0;
+}
+
+weak_alias(setrlimit, setrlimit64);
diff --git a/libc-top-half/musl/src/misc/syscall.c b/libc-top-half/musl/src/misc/syscall.c
new file mode 100644
index 0000000..6f3ef65
--- /dev/null
+++ b/libc-top-half/musl/src/misc/syscall.c
@@ -0,0 +1,21 @@
+#define _BSD_SOURCE
+#include <unistd.h>
+#include "syscall.h"
+#include <stdarg.h>
+
+#undef syscall
+
+long syscall(long n, ...)
+{
+ va_list ap;
+ syscall_arg_t a,b,c,d,e,f;
+ va_start(ap, n);
+ a=va_arg(ap, syscall_arg_t);
+ b=va_arg(ap, syscall_arg_t);
+ c=va_arg(ap, syscall_arg_t);
+ d=va_arg(ap, syscall_arg_t);
+ e=va_arg(ap, syscall_arg_t);
+ f=va_arg(ap, syscall_arg_t);
+ va_end(ap);
+ return __syscall_ret(__syscall(n,a,b,c,d,e,f));
+}
diff --git a/libc-top-half/musl/src/misc/syslog.c b/libc-top-half/musl/src/misc/syslog.c
new file mode 100644
index 0000000..b802acd
--- /dev/null
+++ b/libc-top-half/musl/src/misc/syslog.c
@@ -0,0 +1,162 @@
+#include <stdarg.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <time.h>
+#include <signal.h>
+#include <string.h>
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+#include <pthread.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include "lock.h"
+#include "fork_impl.h"
+
+static volatile int lock[1];
+static char log_ident[32];
+static int log_opt;
+static int log_facility = LOG_USER;
+static int log_mask = 0xff;
+static int log_fd = -1;
+volatile int *const __syslog_lockptr = lock;
+
+int setlogmask(int maskpri)
+{
+ LOCK(lock);
+ int ret = log_mask;
+ if (maskpri) log_mask = maskpri;
+ UNLOCK(lock);
+ return ret;
+}
+
+static const struct {
+ short sun_family;
+ char sun_path[9];
+} log_addr = {
+ AF_UNIX,
+ "/dev/log"
+};
+
+void closelog(void)
+{
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ int cs;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+#endif
+ LOCK(lock);
+ close(log_fd);
+ log_fd = -1;
+ UNLOCK(lock);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(cs, 0);
+#endif
+}
+
+static void __openlog()
+{
+ log_fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
+ if (log_fd >= 0) connect(log_fd, (void *)&log_addr, sizeof log_addr);
+}
+
+void openlog(const char *ident, int opt, int facility)
+{
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ int cs;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+#endif
+ LOCK(lock);
+
+ if (ident) {
+ size_t n = strnlen(ident, sizeof log_ident - 1);
+ memcpy(log_ident, ident, n);
+ log_ident[n] = 0;
+ } else {
+ log_ident[0] = 0;
+ }
+ log_opt = opt;
+ log_facility = facility;
+
+ if ((opt & LOG_NDELAY) && log_fd<0) __openlog();
+
+ UNLOCK(lock);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(cs, 0);
+#endif
+}
+
+static int is_lost_conn(int e)
+{
+ return e==ECONNREFUSED || e==ECONNRESET || e==ENOTCONN || e==EPIPE;
+}
+
+static void _vsyslog(int priority, const char *message, va_list ap)
+{
+ char timebuf[16];
+ time_t now;
+ struct tm tm;
+ char buf[1024];
+ int errno_save = errno;
+ int pid;
+ int l, l2;
+ int hlen;
+ int fd;
+
+ if (log_fd < 0) __openlog();
+
+ if (!(priority & LOG_FACMASK)) priority |= log_facility;
+
+ now = time(NULL);
+ gmtime_r(&now, &tm);
+ strftime(timebuf, sizeof timebuf, "%b %e %T", &tm);
+
+ pid = (log_opt & LOG_PID) ? getpid() : 0;
+ l = snprintf(buf, sizeof buf, "<%d>%s %n%s%s%.0d%s: ",
+ priority, timebuf, &hlen, log_ident, "["+!pid, pid, "]"+!pid);
+ errno = errno_save;
+ l2 = vsnprintf(buf+l, sizeof buf - l, message, ap);
+ if (l2 >= 0) {
+ if (l2 >= sizeof buf - l) l = sizeof buf - 1;
+ else l += l2;
+ if (buf[l-1] != '\n') buf[l++] = '\n';
+ if (send(log_fd, buf, l, 0) < 0 && (!is_lost_conn(errno)
+ || connect(log_fd, (void *)&log_addr, sizeof log_addr) < 0
+ || send(log_fd, buf, l, 0) < 0)
+ && (log_opt & LOG_CONS)) {
+ fd = open("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
+ if (fd >= 0) {
+ dprintf(fd, "%.*s", l-hlen, buf+hlen);
+ close(fd);
+ }
+ }
+ if (log_opt & LOG_PERROR) dprintf(2, "%.*s", l-hlen, buf+hlen);
+ }
+}
+
+static void __vsyslog(int priority, const char *message, va_list ap)
+{
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ int cs;
+#endif
+ if (!(log_mask & LOG_MASK(priority&7)) || (priority&~0x3ff)) return;
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+#endif
+ LOCK(lock);
+ _vsyslog(priority, message, ap);
+ UNLOCK(lock);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+ pthread_setcancelstate(cs, 0);
+#endif
+}
+
+void syslog(int priority, const char *message, ...)
+{
+ va_list ap;
+ va_start(ap, message);
+ __vsyslog(priority, message, ap);
+ va_end(ap);
+}
+
+weak_alias(__vsyslog, vsyslog);
diff --git a/libc-top-half/musl/src/misc/uname.c b/libc-top-half/musl/src/misc/uname.c
new file mode 100644
index 0000000..36e816a
--- /dev/null
+++ b/libc-top-half/musl/src/misc/uname.c
@@ -0,0 +1,32 @@
+#include <sys/utsname.h>
+#ifdef __wasilibc_unmodified_upstream // Implement uname with placeholders
+#include "syscall.h"
+#else
+#include <string.h>
+#endif
+
+int uname(struct utsname *uts)
+{
+#ifdef __wasilibc_unmodified_upstream // Implement uname with placeholders
+ return syscall(SYS_uname, uts);
+#else
+ // Just fill in the fields with placeholder values.
+ strcpy(uts->sysname, "wasi");
+ strcpy(uts->nodename, "(none)");
+ strcpy(uts->release, "0.0.0");
+ strcpy(uts->version, "0.0.0");
+#if defined(__wasm32__)
+ strcpy(uts->machine, "wasm32");
+#elif defined(__wasm64__)
+ strcpy(uts->machine, "wasm64");
+#else
+ strcpy(uts->machine, "unknown");
+#endif
+#ifdef _GNU_SOURCE
+ strcpy(uts->domainname, "(none)");
+#else
+ strcpy(uts->__domainname, "(none)");
+#endif
+ return 0;
+#endif
+}
diff --git a/libc-top-half/musl/src/misc/wordexp.c b/libc-top-half/musl/src/misc/wordexp.c
new file mode 100644
index 0000000..db83a69
--- /dev/null
+++ b/libc-top-half/musl/src/misc/wordexp.c
@@ -0,0 +1,187 @@
+#include <wordexp.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "pthread_impl.h"
+
+static void reap(pid_t pid)
+{
+ int status;
+ while (waitpid(pid, &status, 0) < 0 && errno == EINTR);
+}
+
+static char *getword(FILE *f)
+{
+ char *s = 0;
+ return getdelim(&s, (size_t [1]){0}, 0, f) < 0 ? 0 : s;
+}
+
+static int do_wordexp(const char *s, wordexp_t *we, int flags)
+{
+ size_t i, l;
+ int sq=0, dq=0;
+ size_t np=0;
+ char *w, **tmp;
+ char *redir = (flags & WRDE_SHOWERR) ? "" : "2>/dev/null";
+ int err = 0;
+ FILE *f;
+ size_t wc = 0;
+ char **wv = 0;
+ int p[2];
+ pid_t pid;
+ sigset_t set;
+
+ if (flags & WRDE_REUSE) wordfree(we);
+
+ if (flags & WRDE_NOCMD) for (i=0; s[i]; i++) switch (s[i]) {
+ case '\\':
+ if (!sq && !s[++i]) return WRDE_SYNTAX;
+ break;
+ case '\'':
+ if (!dq) sq^=1;
+ break;
+ case '"':
+ if (!sq) dq^=1;
+ break;
+ case '(':
+ if (np) {
+ np++;
+ break;
+ }
+ case ')':
+ if (np) {
+ np--;
+ break;
+ }
+ case '\n':
+ case '|':
+ case '&':
+ case ';':
+ case '<':
+ case '>':
+ case '{':
+ case '}':
+ if (!(sq|dq|np)) return WRDE_BADCHAR;
+ break;
+ case '$':
+ if (sq) break;
+ if (s[i+1]=='(' && s[i+2]=='(') {
+ i += 2;
+ np += 2;
+ break;
+ } else if (s[i+1] != '(') break;
+ case '`':
+ if (sq) break;
+ return WRDE_CMDSUB;
+ }
+
+ if (flags & WRDE_APPEND) {
+ wc = we->we_wordc;
+ wv = we->we_wordv;
+ }
+
+ i = wc;
+ if (flags & WRDE_DOOFFS) {
+ if (we->we_offs > SIZE_MAX/sizeof(void *)/4)
+ goto nospace;
+ i += we->we_offs;
+ } else {
+ we->we_offs = 0;
+ }
+
+ if (pipe2(p, O_CLOEXEC) < 0) goto nospace;
+ __block_all_sigs(&set);
+ pid = fork();
+ __restore_sigs(&set);
+ if (pid < 0) {
+ close(p[0]);
+ close(p[1]);
+ goto nospace;
+ }
+ if (!pid) {
+ if (p[1] == 1) fcntl(1, F_SETFD, 0);
+ else dup2(p[1], 1);
+ execl("/bin/sh", "sh", "-c",
+ "eval \"printf %s\\\\\\\\0 x $1 $2\"",
+ "sh", s, redir, (char *)0);
+ _exit(1);
+ }
+ close(p[1]);
+
+ f = fdopen(p[0], "r");
+ if (!f) {
+ close(p[0]);
+ kill(pid, SIGKILL);
+ reap(pid);
+ goto nospace;
+ }
+
+ l = wv ? i+1 : 0;
+
+ free(getword(f));
+ if (feof(f)) {
+ fclose(f);
+ reap(pid);
+ return WRDE_SYNTAX;
+ }
+
+ while ((w = getword(f))) {
+ if (i+1 >= l) {
+ l += l/2+10;
+ tmp = realloc(wv, l*sizeof(char *));
+ if (!tmp) break;
+ wv = tmp;
+ }
+ wv[i++] = w;
+ wv[i] = 0;
+ }
+ if (!feof(f)) err = WRDE_NOSPACE;
+
+ fclose(f);
+ reap(pid);
+
+ if (!wv) wv = calloc(i+1, sizeof *wv);
+
+ we->we_wordv = wv;
+ we->we_wordc = i;
+
+ if (flags & WRDE_DOOFFS) {
+ if (wv) for (i=we->we_offs; i; i--)
+ we->we_wordv[i-1] = 0;
+ we->we_wordc -= we->we_offs;
+ }
+ return err;
+
+nospace:
+ if (!(flags & WRDE_APPEND)) {
+ we->we_wordc = 0;
+ we->we_wordv = 0;
+ }
+ return WRDE_NOSPACE;
+}
+
+int wordexp(const char *restrict s, wordexp_t *restrict we, int flags)
+{
+ int r, cs;
+ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+ r = do_wordexp(s, we, flags);
+ pthread_setcancelstate(cs, 0);
+ return r;
+}
+
+void wordfree(wordexp_t *we)
+{
+ size_t i;
+ if (!we->we_wordv) return;
+ for (i=0; i<we->we_wordc; i++) free(we->we_wordv[we->we_offs+i]);
+ free(we->we_wordv);
+ we->we_wordv = 0;
+ we->we_wordc = 0;
+}