9front - general discussion about 9front
 help / color / mirror / Atom feed
From: bsdsm@sdf.org
To: 9front@9front.org
Subject: [9front] [Patch] APE changes (2019 Lufia patches)
Date: Mon, 22 Feb 2021 02:48:32 -0000	[thread overview]
Message-ID: <0e170f2c1818fb21b795c2151e52adaf.squirrel@mx.sdf.org> (raw)

Hello,

This patch is a pared down version of the changes that Lufia made back in
2019; the essential changes from 'add funcs and types to APE' and all of
'add #include_next directive'. An unmodified diff of the former pull
request can be found here[1] for comparison.

This has only been tested on an amd64 build. Works cleanly with tree as of
Feb 20, 2021 changes.


[1]: https://patch-diff.githubusercontent.com/raw/lufia/plan9/pull/5.diff



diff -r bfe93397b157 386/include/ape/_apetypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/386/include/ape/_apetypes.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,7 @@
+#if !defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
+#define	__BYTE_ORDER	__LITTLE_ENDIAN
+#endif
+
+#if !defined(BYTE_ORDER) && defined(LITTLE_ENDIAN)
+#define	BYTE_ORDER	LITTLE_ENDIAN
+#endif
diff -r bfe93397b157 amd64/include/ape/_apetypes.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/amd64/include/ape/_apetypes.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,11 @@
+#ifndef _BITS64
+#define _BITS64
+#endif
+
+#if !defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN)
+#define	__BYTE_ORDER	__LITTLE_ENDIAN
+#endif
+
+#if !defined(BYTE_ORDER) && defined(LITTLE_ENDIAN)
+#define	BYTE_ORDER	LITTLE_ENDIAN
+#endif
diff -r bfe93397b157 sys/include/ape/bsd.h
--- a/sys/include/ape/bsd.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/bsd.h	Fri Feb 12 10:59:32 2021 -0700
@@ -36,6 +36,12 @@
 extern int	rcmd(char**, int, char*, char*, char*, int*);
 extern int	strcasecmp(char*, char*);
 extern int	strncasecmp(char*, char*,int);
+extern unsigned int	arc4random(void);
+extern void	arc4random_buf(void*, size_t);
+extern int	getentropy(void*, size_t);
+
+extern const char*	getprogname(void);
+extern void	setprogname(const char*);

 extern int	getopt(int, char**, char*);
 extern int	opterr;
@@ -44,9 +50,9 @@
 extern char	*optarg;
 extern char	*mktemp(char *);
 extern char	*sys_errlist[];
-extern int		sys_nerr;
+extern int	sys_nerr;

-extern int	gethostname(char*, int);
+extern int	gethostname(char*, size_t);

 #ifdef __cplusplus
 }
diff -r bfe93397b157 sys/include/ape/errno.h
--- a/sys/include/ape/errno.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/errno.h	Fri Feb 12 10:59:32 2021 -0700
@@ -80,6 +80,16 @@
 #define ECANCELED	61
 #define EINPROGRESS	62

+/* from research unix */
+#define ETXTBSY	63
+
+/* Added in more recent 1003.x versions */
+#define EALREADY	64
+#define ECONNRESET	65
+
+#define EOVERFLOW	66
+#define ELOOP		67
+
 #endif /* _POSIX_SOURCE */

 #endif /* __ERRNO */
diff -r bfe93397b157 sys/include/ape/inttypes.h
--- a/sys/include/ape/inttypes.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/inttypes.h	Fri Feb 12 10:59:32 2021 -0700
@@ -11,21 +11,25 @@
 #define PRId16 "d"
 #define PRId32 "d"
 #define PRId64 "lld"
+#define PRIdMAX "lld"

 #define PRIo8 "o"
 #define PRIo16 "o"
 #define PRIo32 "o"
 #define PRIo64 "llo"
+#define PRIoMAX "llo"

 #define PRIx8 "x"
 #define PRIx16 "x"
 #define PRIx32 "x"
 #define PRIx64 "llx"
+#define PRIxMAX "llx"

 #define PRIu8 "u"
 #define PRIu16 "u"
 #define PRIu32 "u"
 #define PRIu64 "llu"
+#define PRIuMAX "llu"

 extern intmax_t strtoimax(const char *, char **, int);

diff -r bfe93397b157 sys/include/ape/lib9.h
--- a/sys/include/ape/lib9.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/lib9.h	Fri Feb 12 10:59:32 2021 -0700
@@ -74,5 +74,6 @@
 extern	unsigned long	getfsr(void);
 extern	void		setfcr(unsigned long);
 extern	void		setfsr(unsigned long);
+extern	vlong		nsec(void);

 #endif
diff -r bfe93397b157 sys/include/ape/libgen.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/include/ape/libgen.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,16 @@
+#ifndef __LIBGEN_H
+#define __LIBGEN_H
+#pragma lib "/$M/lib/ape/libap.a"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern char *dirname(char *path);
+extern char *basename(char *path);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r bfe93397b157 sys/include/ape/machine/endian.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/include/ape/machine/endian.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,10 @@
+#ifndef _ENDIAN_H_
+#define _ENDIAN_H_
+
+#define LITTLE_ENDIAN	1234
+#define BIG_ENDIAN	4321
+#define PDP_ENDIAN	3412
+
+#include "_apetypes.h"
+
+#endif
diff -r bfe93397b157 sys/include/ape/netdb.h
--- a/sys/include/ape/netdb.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/netdb.h	Fri Feb 12 10:59:32 2021 -0700
@@ -147,6 +147,8 @@
 #define NI_NUMERICSCOPE	0x0010	/* For IPv6 addresses, the numeric form of
the scope identifier is returned
 				   instead of its name. */
 #define NI_DGRAM	0x0020	/* Indicates that the service is a datagram
service (SOCK_DGRAM). */
+#define NI_MAXHOST	1025
+#define NI_MAXSERV	32

 /* Error values for `getaddrinfo' and `getnameinfo' functions.  */
 #define EAI_BADFLAGS	  -1	/* Invalid value for `ai_flags' field */
diff -r bfe93397b157 sys/include/ape/poll.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/include/ape/poll.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,41 @@
+#ifndef __POLL_H
+#define __POLL_H
+#pragma lib "/$M/lib/ape/libap.a"
+
+#ifndef	FD_SETSIZE
+#define	FD_SETSIZE	96
+#endif
+
+struct pollfd {
+	int fd;			/* file descriptor */
+	short events;	/* events to look for */
+	short revents;	/* events returned */
+};
+
+typedef unsigned long nfds_t;
+
+#define	POLLIN		0x001
+#define	POLLPRI		0x002
+#define	POLLOUT		0x004
+#define	POLLERR		0x008
+#define	POLLHUP		0x010
+#define	POLLNVAL	0x020
+
+#define	POLLRDNORM	0x040
+#define	POLLRDBAND	0x080
+#define	POLLWRNORM	POLLOUT
+#define	POLLWRBAND	0x100
+
+#define	INFTIM	-1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int poll(struct pollfd fds[], nfds_t nfds, int timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r bfe93397b157 sys/include/ape/pthread.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/include/ape/pthread.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,105 @@
+#ifndef __PTHREAD_H
+#define __PTHREAD_H
+#pragma lib "/$M/lib/ape/libpthread.a"
+
+#define _LOCK_EXTENSION
+#define _QLOCK_EXTENSION
+#include <sys/types.h>
+#include <unistd.h>
+#include <lock.h>
+#include <qlock.h>
+
+typedef struct pthread_once pthread_once_t;
+typedef pid_t pthread_t;
+typedef int pthread_attr_t;
+typedef struct pthread_mutex pthread_mutex_t;
+typedef int pthread_mutexattr_t;
+typedef struct pthread_cond pthread_cond_t;
+typedef int pthread_condattr_t;
+typedef struct pthread_key pthread_key_t;
+
+enum {
+	PTHREAD_THREADS_MAX = 1000,
+
+	PTHREAD_CANCEL_DISABLE = 1,
+};
+
+struct pthread_once {
+	Lock l;
+	int once;
+};
+struct pthread_mutex {
+	QLock l;
+
+	Lock mu;
+	pthread_t pid;
+	int ref;
+	pthread_mutexattr_t attr;
+};
+struct pthread_cond {
+	QLock l;
+	Rendez r;
+};
+struct pthread_key {
+	Lock l;
+	void (*destroy)(void*);
+	struct {
+		pthread_t	pid;
+		const void	*p;
+	} *arenas;
+	int n;
+};
+
+#define PTHREAD_ONCE_INIT		{ 0 }
+#define PTHREAD_MUTEX_INITIALIZER	{ 0 }
+#define PTHREAD_MUTEX_DEFAULT		0
+#define PTHREAD_MUTEX_NORAML		1
+#define PTHREAD_MUTEX_RECURSIVE	2
+#define PTHREAD_COND_INITIALIZER	{ 0 }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int	pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+extern int	pthread_once(pthread_once_t*, void (*)(void));
+extern pthread_t	pthread_self(void);
+extern int	pthread_equal(pthread_t, pthread_t);
+extern int	pthread_create(pthread_t*, pthread_attr_t*, void *(*)(void*),
void*);
+extern void	pthread_exit(void*);
+extern int	pthread_join(pthread_t, void**);
+
+extern int	pthread_mutexattr_init(pthread_mutexattr_t*);
+extern int	pthread_mutexattr_destroy(pthread_mutexattr_t*);
+extern int	pthread_mutexattr_settype(pthread_mutexattr_t*, int);
+
+extern int	pthread_mutex_init(pthread_mutex_t*, const pthread_mutexattr_t*);
+extern int	pthread_mutex_lock(pthread_mutex_t*);
+extern int	pthread_mutex_unlock(pthread_mutex_t*);
+extern int	pthread_mutex_trylock(pthread_mutex_t*);
+extern int	pthread_mutex_destroy(pthread_mutex_t*);
+
+extern int	pthread_cond_init(pthread_cond_t*, pthread_condattr_t*);
+extern int	pthread_cond_wait(pthread_cond_t*, pthread_mutex_t*);
+extern int	pthread_cond_signal(pthread_cond_t*);
+extern int	pthread_cond_broadcast(pthread_cond_t*);
+extern int	pthread_cond_destroy(pthread_cond_t*);
+
+extern int	pthread_key_create(pthread_key_t*, void (*)(void*));
+extern int	pthread_key_delete(pthread_key_t);
+extern void	*pthread_getspecific(pthread_key_t);
+extern int	pthread_setspecific(pthread_key_t, const void*);
+
+extern int	pthread_setcancelstate(int, int*);
+
+#ifndef _PTHREAD_SIGMASK
+#define _PTHREAD_SIGMASK
+#include <signal.h>
+extern int	pthread_sigmask(int, const sigset_t*, sigset_t*);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r bfe93397b157 sys/include/ape/qlock.h
--- a/sys/include/ape/qlock.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/qlock.h	Fri Feb 12 10:59:32 2021 -0700
@@ -26,6 +26,14 @@
 	QLp 	*tail;
 } QLock;

+typedef
+struct Rendez
+{
+	QLock	*l;
+	QLp	*head;
+	QLp	*tail;
+} Rendez;
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -34,6 +42,10 @@
 extern	void	qunlock(QLock*);
 extern	int	canqlock(QLock*);

+extern	void	rsleep(Rendez*);
+extern	int	rwakeup(Rendez*);
+extern	int	rwakeupall(Rendez*);
+
 #ifdef __cplusplus
 }
 #endif
diff -r bfe93397b157 sys/include/ape/signal.h
--- a/sys/include/ape/signal.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/signal.h	Fri Feb 12 10:59:32 2021 -0700
@@ -37,11 +37,12 @@
 #define SIGTSTP	18	/* interactive stop */
 #define SIGTTIN	19	/* read from ctl tty by member of background */
 #define SIGTTOU	20	/* write to ctl tty by member of background */
-#define SIGVTALRM 21 /* virtual alarm clock */
-#define SIGPROF 22  /* profiling alarm clock */
+#define SIGWINCH 21	/* window size changes */
+#define SIGVTALRM 22 /* virtual alarm clock */
+#define SIGPROF 23  /* profiling alarm clock */

 #ifdef _BSD_EXTENSION
-#define NSIG 23
+#define NSIG 24
 #endif

 #ifdef __cplusplus
@@ -65,6 +66,10 @@
 };
 /* values for sa_flags */
 #define SA_NOCLDSTOP	1
+#define SA_ONSTACK	2
+#define SA_RESETHAND	3
+#define SA_RESTART	4
+#define SA_RESTORER	5

 /* first argument to sigprocmask */
 #define SIG_BLOCK	1
diff -r bfe93397b157 sys/include/ape/stdint.h
--- a/sys/include/ape/stdint.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/stdint.h	Fri Feb 12 10:59:32 2021 -0700
@@ -10,6 +10,15 @@
 typedef unsigned int _uintptr_t;
 #endif

+typedef char s8;
+typedef short s16;
+typedef long s32;
+typedef long long s64;
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned long u32;
+typedef unsigned long long u64;
+
 typedef char int8_t;
 typedef short int16_t;
 typedef int int32_t;
diff -r bfe93397b157 sys/include/ape/stdlib.h
--- a/sys/include/ape/stdlib.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/stdlib.h	Fri Feb 12 10:59:32 2021 -0700
@@ -49,6 +49,10 @@
 extern size_t mbstowcs(wchar_t *, const char *, size_t);
 extern size_t wcstombs(char *, const wchar_t *, size_t);

+#ifdef _BSD_EXTENSION
+#include <bsd.h>
+#endif
+
 #ifdef _POSIX_C_SOURCE
 extern int mkstemp(char *template);
 #endif
diff -r bfe93397b157 sys/include/ape/sys/resource.h
--- a/sys/include/ape/sys/resource.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/sys/resource.h	Fri Feb 12 10:59:32 2021 -0700
@@ -5,6 +5,17 @@
     This header file is an extension to ANSI/POSIX
 #endif

+#include <sys/time.h>
+
+#pragma lib "/$M/lib/ape/libap.a"
+
+enum {
+	RUSAGE_SELF = 0,
+	RUSAGE_CHILDREN = -1
+};
+
+#define RUSAGE_SELF		RUSAGE_SELF
+#define RUSAGE_CHILDREN		RUSAGE_CHILDREN
 struct rusage {
 	struct timeval ru_utime;	/* user time used */
 	struct timeval ru_stime;	/* system time used */
@@ -26,4 +37,14 @@
 #define	ru_last		ru_nivcsw
 };

+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int getrusage(int, struct rusage *);
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* !__RESOURCE_H__ */
diff -r bfe93397b157 sys/include/ape/sys/socket.h
--- a/sys/include/ape/sys/socket.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/sys/socket.h	Fri Feb 12 10:59:32 2021 -0700
@@ -24,6 +24,7 @@
  */
 typedef int socklen_t;
 typedef unsigned short sa_family_t;
+typedef unsigned short in_port_t;

 /*
  * Types
@@ -178,6 +179,15 @@

 #define	MSG_MAXIOVLEN	16

+#define TCP_NODELAY	1
+#define TCP_MAXSEG	2
+
+enum {
+	SHUT_RD,		/* no more receptions */
+	SHUT_WR,		/* no more transmissions */
+	SHUT_RDWR,		/* no more receptions or transmissions */
+};
+
 extern int accept(int, void *, int *);
 extern int bind(int, void *, int);
 extern int connect(int, void *, int);
diff -r bfe93397b157 sys/include/ape/sys/stat.h
--- a/sys/include/ape/sys/stat.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/sys/stat.h	Fri Feb 12 10:59:32 2021 -0700
@@ -27,6 +27,7 @@
 #define	S__MASK		     0170000
 #ifdef _RESEARCH_SOURCE
 #define S_ISLNK(m)	(((m)&S__MASK) == 0120000)
+#define S_ISSOCK(m)	(((m)&S__MASK) == 0010000)
 #endif
 #define S_ISREG(m)	(((m)&S__MASK) == 0100000)
 #define S_ISDIR(m)	(((m)&S__MASK) == 0040000)
diff -r bfe93397b157 sys/include/ape/sys/types.h
--- a/sys/include/ape/sys/types.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/sys/types.h	Fri Feb 12 10:59:32 2021 -0700
@@ -2,6 +2,7 @@
 #define __TYPES_H

 #pragma lib "/$M/lib/ape/libap.a"
+
 typedef	unsigned short	ino_t;
 typedef	unsigned short	dev_t;
 typedef	long long		off_t;
@@ -10,6 +11,11 @@
 typedef short		gid_t;
 typedef short		nlink_t;
 typedef int		pid_t;
+typedef unsigned char	u_char;
+typedef unsigned short	u_short;
+typedef unsigned int	u_int;
+typedef unsigned long	u_long;
+typedef unsigned int	in_addr_t;

 #ifndef _SIZE_T
 #define _SIZE_T
@@ -25,6 +31,11 @@
 typedef long time_t;
 #endif

+#ifndef _CLOCKID_T
+#define _CLOCKID_T
+typedef int clockid_t;
+#endif
+
 #ifdef _BSD_EXTENSION
 #ifndef _CADDR_T
 #define _CADDR_T
diff -r bfe93397b157 sys/include/ape/syslog.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/include/ape/syslog.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,57 @@
+#ifndef __SYSLOG_H
+#define __SYSLOG_H
+#pragma lib "/$M/lib/ape/libap.a"
+
+enum {
+	/* facility */
+	LOG_KERN	= 0<<3,
+	LOG_USER	= 1<<3,
+	LOG_DAEMON	= 3<<3,
+	LOG_AUTH	= 4<<3,
+	LOG_SYSLOG	= 5<<3,
+	LOG_CRON	= 9<<3,
+	LOG_AUTHPRIV= 10<<3,
+	LOG_LOCAL0	= 16<<3,
+	LOG_LOCAL1	= 17<<3,
+	LOG_LOCAL2	= 18<<3,
+	LOG_LOCAL3	= 19<<3,
+	LOG_LOCAL4	= 20<<3,
+	LOG_LOCAL5	= 21<<3,
+	LOG_LOCAL6	= 22<<3,
+	LOG_LOCAL7	= 23<<3,
+};
+
+enum {
+	/* priority */
+	LOG_EMERG,
+	LOG_ALERT,
+	LOG_CRIT,
+	LOG_ERR,
+	LOG_WARNING,
+	LOG_NOTICE,
+	LOG_INFO,
+	LOG_DEBUG,
+};
+
+enum {
+	/* option */
+	LOG_PID		= 0x01,
+	LOG_CONS	= 0x02,
+	LOG_ODELAY	= 0x04,
+	LOG_NDELAY	= 0x08,
+	LOG_NOWAIT	= 0x10,
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void openlog(const char *, int, int);
+extern void syslog(int, const char *, ...);
+extern void closelog(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff -r bfe93397b157 sys/include/ape/time.h
--- a/sys/include/ape/time.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/time.h	Fri Feb 12 10:59:32 2021 -0700
@@ -9,6 +9,9 @@
 /* obsolsecent, but required */
 #define CLK_TCK CLOCKS_PER_SEC

+#define CLOCK_REALTIME 0
+#define CLOCK_MONOTONIC 1
+
 #ifndef _CLOCK_T
 #define _CLOCK_T
 typedef long clock_t;
@@ -17,6 +20,10 @@
 #define _TIME_T
 typedef long time_t;
 #endif
+#ifndef _CLOCKID_T
+#define _CLOCKID_T
+typedef int clockid_t;
+#endif

 struct tm {
 	int	tm_sec;
@@ -43,6 +50,8 @@
 extern struct tm *gmtime(const time_t *);
 extern struct tm *localtime(const time_t *);
 extern size_t strftime(char *, size_t, const char *, const struct tm *);
+extern int clock_gettime(clockid_t, struct timespec *);
+extern int clock_settime(clockid_t, struct timespec *);

 #ifdef _REENTRANT_SOURCE
 extern struct tm *gmtime_r(const time_t *, struct tm *);
diff -r bfe93397b157 sys/include/ape/unistd.h
--- a/sys/include/ape/unistd.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/include/ape/unistd.h	Fri Feb 12 10:59:32 2021 -0700
@@ -62,6 +62,7 @@
 #define	_SC_SAVED_IDS		9	/* saved suid/sgid per process */
 #define	_SC_VERSION		10	/* this version */
 #define _SC_LOGIN_NAME_MAX	11	/* max length of a login name */
+#define _SC_PAGESIZE		12

 /* pathconf argument */
 #define _PC_LINK_MAX		1
@@ -115,6 +116,7 @@
 extern int setgid(gid_t);
 extern int getgroups(int, gid_t *);
 extern pid_t getpgrp(void);
+extern int getpgid(pid_t);
 extern int setpgid(pid_t, pid_t);
 extern pid_t setsid(void);
 #endif
@@ -130,6 +132,7 @@
 extern int access(const char *, int);
 extern long pathconf(const char *, int);
 extern long fpathconf(int, int);
+extern int fchdir(int);
 #ifdef __TYPES_H
 extern int chown(const char *, uid_t, gid_t);
 #endif
@@ -144,6 +147,9 @@
 #ifdef __TYPES_H
 extern int ftruncate(int, off_t);
 extern off_t lseek(int, off_t, int);
+
+extern ssize_t pread(int, void *, size_t, off_t);
+extern ssize_t pwrite(int, const void *, size_t, off_t);
 #endif

 /* device- and class-specific functions */
@@ -159,8 +165,12 @@
 /* berkeley specific functions */
 #ifdef _BSD_EXTENSION
 #include <bsd.h>
+
+extern int getpagesize(void);
 #endif

+extern int gethostname(char *, size_t);
+
 #ifdef __cplusplus
 }
 #endif
diff -r bfe93397b157 sys/src/ape/lib/9/mkfile
--- a/sys/src/ape/lib/9/mkfile	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/9/mkfile	Fri Feb 12 10:59:32 2021 -0700
@@ -13,6 +13,7 @@
 	getfcr.$O\
 	getfields.$O\
 	mount.$O\
+	nsec.$O\
 	rendezvous.$O\
 	rfork.$O\
 	segattach.$O\
diff -r bfe93397b157 sys/src/ape/lib/9/nsec.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/9/nsec.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,9 @@
+#include <lib9.h>
+
+extern vlong _NSEC(void);
+
+vlong
+nsec(void)
+{
+	return _NSEC();
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/clock_gettime.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/clock_gettime.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,33 @@
+#include <time.h>
+#include <sys/times.h>
+#include <lib9.h>
+#include <errno.h>
+
+#define NANO_IN_SEC 1000000000L
+
+int
+clock_gettime(clockid_t clock_id, struct timespec *tp)
+{
+	vlong ns;
+
+	switch(clock_id){
+	case CLOCK_REALTIME:
+	case CLOCK_MONOTONIC:
+		ns = nsec();
+		tp->tv_sec = ns/NANO_IN_SEC;
+		tp->tv_nsec = ns%NANO_IN_SEC;
+		return 0;
+	default:
+		errno = EINVAL;
+		return -1;
+	}
+}
+
+int
+clock_settime(clockid_t clock_id, struct timespec *tp)
+{
+	USED(clock_id);
+	USED(tp);
+	errno = EPERM;
+	return -1;
+}
diff -r 02e3059af5bc sys/src/ape/lib/ap/plan9/dirstat.c
--- a/sys/src/ape/lib/ap/plan9/dirstat.c	Thu Feb 11 09:37:36 2021 +0100
+++ b/sys/src/ape/lib/ap/plan9/dirstat.c	Fri Feb 12 10:59:32 2021 -0700
@@ -63,11 +63,11 @@

 	nd = DIRSIZE;
 	for(i=0; i<2; i++){	/* should work by the second try */
-		d = malloc(sizeof(Dir) + nd);
+		d = malloc(sizeof(Dir) + BIT16SZ +nd);
 		if(d == nil)
 			return nil;
 		buf = (uchar*)&d[1];
-		n = _FSTAT(fd, buf, nd);
+		n = _FSTAT(fd, buf, BIT16SZ+nd);
 		if(n < BIT16SZ){
 			free(d);
 			return nil;
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/fchdir.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/fchdir.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,32 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <limits.h>
+#include "lib.h"
+#include <errno.h>
+
+extern int _FD2PATH(int fd, char *buf, int nbuf);
+extern int _CHDIR(char *dirname);
+
+int
+fchdir(int fd)
+{
+	char buf[_POSIX_PATH_MAX];
+	struct stat s;
+	int n;
+
+	if(fstat(fd, &s) < 0)
+		return -1;
+	if(!S_ISDIR(s.st_mode)){
+		errno = ENOTDIR;
+		return -1;
+	}
+
+	if (_FD2PATH(fd, buf, sizeof buf) < 0){
+		_syserrno();
+		return -1;
+	}
+	n = _CHDIR(buf);
+	if(n < 0)
+		_syserrno();
+	return n;
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/fork.c
--- a/sys/src/ape/lib/ap/plan9/fork.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/plan9/fork.c	Fri Feb 12 10:59:32 2021 -0700
@@ -2,18 +2,58 @@
 #include <errno.h>
 #include <unistd.h>
 #include "sys9.h"
+#include <pthread.h>
+
+enum {
+	NHANDLERS = 100
+};
+
+static void (*preparehdlr[NHANDLERS])(void);
+static void (*parenthdlr[NHANDLERS])(void);
+static void (*childhdlr[NHANDLERS])(void);
+static int nprepare;
+static int nparent;
+static int nchild;
+
+int
+pthread_atfork(void (*prepare)(void), void (*parent)(void), void
(*child)(void))
+{
+	if(prepare != NULL){
+		if(nprepare >= NHANDLERS)
+			return ENOMEM;
+		preparehdlr[nprepare++] = prepare;
+	}
+	if(parent != NULL){
+		if(nparent >= NHANDLERS)
+			return ENOMEM;
+		parenthdlr[nparent++] = parent;
+	}
+	if(child != NULL){
+		if(nchild >= NHANDLERS)
+			return ENOMEM;
+		childhdlr[nchild++] = child;
+	}
+	return 0;
+}

 pid_t
 fork(void)
 {
-	int n;
+	int n, i;

+	for(i = nprepare-1; i >= 0; i--)
+		preparehdlr[i]();
 	n = _RFORK(RFENVG|RFFDG|RFPROC);
 	if(n < 0)
 		_syserrno();
 	if(n == 0) {
 		_detachbuf();
 		_sessleader = 0;
+		for(i = 0; i < nchild; i++)
+			childhdlr[i]();
+		return 0;
 	}
+	for(i = 0; i < nparent; i++)
+		parenthdlr[i]();
 	return n;
 }
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/fsync.c
--- a/sys/src/ape/lib/ap/plan9/fsync.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/plan9/fsync.c	Fri Feb 12 10:59:32 2021 -0700
@@ -5,6 +5,6 @@
 int
 fsync(int)
 {
-	errno = EINVAL;
-	return -1;
+	/* TODO: should fsync return an error? */
+	return 0;
 }
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/getpgid.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/getpgid.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,31 @@
+#include "lib.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "sys9.h"
+
+int
+getpgid(pid_t pid)
+{
+	int n, f;
+	char buf[50], fname[30];
+
+	if(pid == 0)
+		pid = getpid();
+	sprintf(fname, "/proc/%d/noteid", pid);
+	f = open(fname, 0);
+	if(f < 0) {
+		errno = ESRCH;
+		return -1;
+	}
+	n = read(f, buf, sizeof(buf));
+	if(n < 0)
+		_syserrno();
+	else{
+		buf[n] = '\0';
+		n = atoi(buf);
+	}
+	close(f);
+	return n;
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/getrusage.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/getrusage.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,12 @@
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <string.h>
+
+int
+getrusage(int who, struct rusage *usage)
+{
+	/* dummy implementation */
+	USED(who);
+	memset(usage, 0, sizeof *usage);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/mkfile
--- a/sys/src/ape/lib/ap/plan9/mkfile	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/plan9/mkfile	Fri Feb 12 10:59:32 2021 -0700
@@ -9,6 +9,7 @@
 	_exit.$O\
 	_fdinfo.$O\
 	_getpw.$O\
 	_nap.$O\
 	9mallocz.$O\
 	9nsec.$O\
@@ -25,6 +26,7 @@
 	chroot.$O\
 	chmod.$O\
 	chown.$O\
+	clock_gettime.$O\
 	close.$O\
 	convM2D.$O\
 	convD2M.$O\
@@ -42,6 +44,7 @@
 	execv.$O\
 	execve.$O\
 	execvp.$O\
+	fchdir.$O\
 	fcntl.$O\
 	fork.$O\
 	frexp.$O\
@@ -54,11 +57,13 @@
 	getgrnam.$O\
 	getgroups.$O\
 	getlogin.$O\
+	getpgid.$O\
 	getpgrp.$O\
 	getpid.$O\
 	getppid.$O\
 	getpwnam.$O\
 	getpwuid.$O\
+	getrusage.$O\
 	getuid.$O\
 	isatty.$O\
 	kill.$O\
@@ -71,6 +76,7 @@
 	opendir.$O\
 	pause.$O\
 	pipe.$O\
+	poll.$O\
 	profile.$O\
 	qlock.$O\
 	read.$O\
@@ -87,6 +93,7 @@
 	sleep.$O\
 	sqrt.$O\
 	stat.$O\
+	syslog.$O\
 	system.$O\
 	tcgetattr.$O\
 	time.$O\
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/poll.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/poll.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,57 @@
+#include <stdio.h>
+#include <sys/time.h>
+#include <sys/select.h>
+#include <poll.h>
+
+int
+poll(struct pollfd *fds, nfds_t nfds, int timeout)
+{
+	int n;
+	fd_set rfds, wfds, efds;
+	struct timeval w, *wp;
+	struct pollfd *p, *ep;
+
+	n = -1;
+	FD_ZERO(&rfds);
+	FD_ZERO(&wfds);
+	FD_ZERO(&efds);
+
+	ep = fds + nfds;
+	for(p = fds; p < ep; p++){
+		if(p->fd < 0)
+			continue;
+		if((p->events&(POLLIN|POLLPRI|POLLOUT)) == 0)
+			continue;
+		if(p->events&POLLIN)
+			FD_SET(p->fd, &rfds);
+		if(p->events&POLLOUT)
+			FD_SET(p->fd, &wfds);
+		if(p->events&(POLLPRI))
+			FD_SET(p->fd, &efds);
+		if(p->fd > n)
+			n = p->fd;
+	}
+	wp = NULL;
+	if(timeout >= 0){
+		w.tv_sec = timeout/1000;
+		w.tv_usec = (timeout%1000)*1000;
+		wp = &w;
+	}
+	n = select(n+1, &rfds, &wfds, &efds, wp);
+	if(n < 0)
+		return -1;
+
+	/* POLLHUP means the socket is no longer connected. (FIN) */
+	/* POLLERR means the socket got an asynchronous error. (RST) */
+
+	for(p = fds; p < ep; p++){
+		p->revents = 0;
+		if(FD_ISSET(p->fd, &rfds))
+			p->revents |= POLLIN;
+		if(FD_ISSET(p->fd, &wfds))
+			p->revents |= POLLOUT;
+		if(FD_ISSET(p->fd, &efds))
+			p->revents |= POLLPRI|POLLHUP;
+	}
+	return n;
+}
diff -r 02e3059af5bc -r 5904c2b92376 sys/src/ape/lib/ap/plan9/qlock.c
--- a/sys/src/ape/lib/ap/plan9/qlock.c	Thu Feb 11 09:37:36 2021 +0100
+++ b/sys/src/ape/lib/ap/plan9/qlock.c	Thu Oct 26 02:42:26 2017 +0200
@@ -22,6 +22,9 @@
 enum
 {
 	Queuing,
+	QueuingR,
+	QueuingW,
+	Sleeping,
 };

 /* find a free shared memory location to queue ourselves in */
@@ -108,3 +112,254 @@
 	unlock(&q->lock);
 	return 0;
 }
+
+#if 0
+
+void
+rlock(RWLock *q)
+{
+	QLp *p, *mp;
+
+	lock(&q->lock);
+	if(q->writer == 0 && q->head == nil){
+		/* no writer, go for it */
+		q->readers++;
+		unlock(&q->lock);
+		return;
+	}
+
+	mp = getqlp();
+	p = q->tail;
+	if(p == 0)
+		q->head = mp;
+	else
+		p->next = mp;
+	q->tail = mp;
+	mp->next = nil;
+	mp->state = QueuingR;
+	unlock(&q->lock);
+
+	/* wait in kernel */
+	while((*_rendezvousp)(mp, (void*)1) == (void*)~0)
+		;
+	mp->inuse = 0;
+}
+
+int
+canrlock(RWLock *q)
+{
+	lock(&q->lock);
+	if (q->writer == 0 && q->head == nil) {
+		/* no writer; go for it */
+		q->readers++;
+		unlock(&q->lock);
+		return 1;
+	}
+	unlock(&q->lock);
+	return 0;
+}
+
+void
+runlock(RWLock *q)
+{
+	QLp *p;
+
+	lock(&q->lock);
+	if(q->readers <= 0)
+		abort();
+	p = q->head;
+	if(--(q->readers) > 0 || p == nil){
+		unlock(&q->lock);
+		return;
+	}
+
+	/* start waiting writer */
+	if(p->state != QueuingW)
+		abort();
+	q->head = p->next;
+	if(q->head == 0)
+		q->tail = 0;
+	q->writer = 1;
+	unlock(&q->lock);
+
+	/* wakeup waiter */
+	while((*_rendezvousp)(p, (void*)0) == (void*)~0)
+		;
+}
+
+void
+wlock(RWLock *q)
+{
+	QLp *p, *mp;
+
+	lock(&q->lock);
+	if(q->readers == 0 && q->writer == 0){
+		/* noone waiting, go for it */
+		q->writer = 1;
+		unlock(&q->lock);
+		return;
+	}
+
+	/* wait */
+	p = q->tail;
+	mp = getqlp();
+	if(p == nil)
+		q->head = mp;
+	else
+		p->next = mp;
+	q->tail = mp;
+	mp->next = nil;
+	mp->state = QueuingW;
+	unlock(&q->lock);
+
+	/* wait in kernel */
+	while((*_rendezvousp)(mp, (void*)1) == (void*)~0)
+		;
+	mp->inuse = 0;
+}
+
+int
+canwlock(RWLock *q)
+{
+	lock(&q->lock);
+	if (q->readers == 0 && q->writer == 0) {
+		/* no one waiting; go for it */
+		q->writer = 1;
+		unlock(&q->lock);
+		return 1;
+	}
+	unlock(&q->lock);
+	return 0;
+}
+
+void
+wunlock(RWLock *q)
+{
+	QLp *p;
+
+	lock(&q->lock);
+	if(q->writer == 0)
+		abort();
+	p = q->head;
+	if(p == nil){
+		q->writer = 0;
+		unlock(&q->lock);
+		return;
+	}
+	if(p->state == QueuingW){
+		/* start waiting writer */
+		q->head = p->next;
+		if(q->head == nil)
+			q->tail = nil;
+		unlock(&q->lock);
+		while((*_rendezvousp)(p, (void*)0) == (void*)~0)
+			;
+		return;
+	}
+
+	if(p->state != QueuingR)
+		abort();
+
+	/* wake waiting readers */
+	while(q->head != nil && q->head->state == QueuingR){
+		p = q->head;
+		q->head = p->next;
+		q->readers++;
+		while((*_rendezvousp)(p, (void*)0) == (void*)~0)
+			;
+	}
+	if(q->head == nil)
+		q->tail = nil;
+	q->writer = 0;
+	unlock(&q->lock);
+}
+
+void
+rsleep(Rendez *r)
+{
+	QLp *t, *me;
+
+	if(!r->l)
+		abort();
+	lock(&r->l->lock);
+	/* we should hold the qlock */
+	if(!r->l->locked)
+		abort();
+
+	/* add ourselves to the wait list */
+	me = getqlp();
+	me->state = Sleeping;
+	if(r->head == nil)
+		r->head = me;
+	else
+		r->tail->next = me;
+	me->next = nil;
+	r->tail = me;
+
+	/* pass the qlock to the next guy */
+	t = r->l->head;
+	if(t){
+		r->l->head = t->next;
+		if(r->l->head == nil)
+			r->l->tail = nil;
+		unlock(&r->l->lock);
+		while((*_rendezvousp)(t, (void*)0x12345) == (void*)~0)
+			;
+	}else{
+		r->l->locked = 0;
+		unlock(&r->l->lock);
+	}
+
+	/* wait for a wakeup */
+	while((*_rendezvousp)(me, (void*)1) == (void*)~0)
+		;
+	me->inuse = 0;
+}
+
+int
+rwakeup(Rendez *r)
+{
+	QLp *t;
+
+	/*
+	 * take off wait and put on front of queue
+	 * put on front so guys that have been waiting will not get starved
+	 */
+
+	if(!r->l)
+		abort();
+	lock(&r->l->lock);
+	if(!r->l->locked)
+		abort();
+
+	t = r->head;
+	if(t == nil){
+		unlock(&r->l->lock);
+		return 0;
+	}
+
+	r->head = t->next;
+	if(r->head == nil)
+		r->tail = nil;
+
+	t->next = r->l->head;
+	r->l->head = t;
+	if(r->l->tail == nil)
+		r->l->tail = t;
+
+	t->state = Queuing;
+	unlock(&r->l->lock);
+	return 1;
+}
+
+int
+rwakeupall(Rendez *r)
+{
+	int i;
+
+	for(i=0; rwakeup(r); i++)
+		;
+	return i;
+}
+
+#endif
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/read.c
--- a/sys/src/ape/lib/ap/plan9/read.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/plan9/read.c	Fri Feb 12 10:59:32 2021 -0700
@@ -1,4 +1,5 @@
 #include <errno.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include <string.h>
 #include "lib.h"
@@ -7,7 +8,7 @@
 #include <stdio.h>

 ssize_t
-read(int d, void *buf, size_t nbytes)
+pread(int d, void *buf, size_t nbytes, off_t offset)
 {
 	int n, noblock, isbuf;
 	Fdinfo *f;
@@ -38,9 +39,15 @@
 		}
 		n = _readbuf(d, buf, nbytes, noblock);
 	}else{
-		n = _READ(d, buf, nbytes);
+		n = _PREAD(d, buf, nbytes, offset);
 		if(n < 0)
 			_syserrno();
 	}
 	return n;
 }
+
+ssize_t
+read(int d, void *buf, size_t nbytes)
+{
+	return pread(d, buf, nbytes, -1LL);
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/syslog.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/plan9/syslog.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,104 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <syslog.h>
+
+static struct {
+	const char *ident;
+	char hostname[128];
+	int option;
+	int facility;
+	int fd;
+	int consfd;
+} flags = {
+	.fd = -1,
+	.consfd = -1,
+};
+
+void
+openlog(const char *ident, int option, int facility)
+{
+	char buf[1024];
+	int fd;
+
+	closelog();
+	if(gethostname(flags.hostname, sizeof(flags.hostname)) < 0)
+		return;
+	if(ident){
+		snprintf(buf, sizeof(buf), "/sys/log/%s", ident);
+		fd = open(buf, O_WRONLY);
+		if(fd < 0)
+			return;
+		if(fcntl(fd, F_SETFD, FD_CLOEXEC) < 0){
+			close(fd);
+			return;
+		}
+		flags.fd = fd;
+	}
+	if(option&LOG_CONS){
+		fd = open("/dev/cons", O_WRONLY);
+		if(fd < 0){
+			closelog();
+			return;
+		}
+		if(fcntl(fd, F_SETFD, FD_CLOEXEC) < 0){
+			closelog();
+			return;
+		}
+		flags.consfd = fd;
+	}
+	flags.ident = ident;
+	flags.option = option;
+	flags.facility = facility;
+}
+
+void
+syslog(int priority, const char *format, ...)
+{
+	char buf[128], *s, *p;
+	time_t t;
+	int n;
+	va_list arg;
+
+	/* syslog => Mar 10 01:45:50 $hostname $prog[$pid]: $msg */
+	/* plan9  => $hostname Mar 10 01:45:50 $msg */
+
+	USED(priority);
+
+	/* TODO: lock */
+	t = time(NULL);
+	s = ctime(&t);
+	p = buf + snprintf(buf, sizeof(buf)-1, "%s ", flags.hostname);
+	strncpy(p, s+4, 15);
+	p += 15;
+	*p++ = ' ';
+	va_start(arg, format);
+	p += vsnprintf(p, buf+sizeof(buf)-p-1, format, arg);
+	va_end(arg);
+	*p++ = '\n';
+	n = p - buf;
+	if(flags.fd >= 0){
+		lseek(flags.fd, 0, 2);
+		write(flags.fd, buf, n);
+	}
+	if(flags.consfd >= 0)
+		write(flags.consfd, buf, n);
+}
+
+void
+closelog(void)
+{
+	flags.ident = NULL;
+	flags.hostname[0] = '\0';
+	flags.option = 0;
+	flags.facility = 0;
+	if(flags.fd >= 0)
+		close(flags.fd);
+	flags.fd = -1;
+	if(flags.consfd >= 0)
+		close(flags.consfd);
+	flags.consfd = -1;
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/plan9/write.c
--- a/sys/src/ape/lib/ap/plan9/write.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/plan9/write.c	Fri Feb 12 10:59:32 2021 -0700
@@ -1,10 +1,11 @@
 #include <errno.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include "lib.h"
 #include "sys9.h"

 ssize_t
-write(int d, const void *buf, size_t nbytes)
+pwrite(int d, const void *buf, size_t nbytes, off_t offset)
 {
 	int n;

@@ -14,8 +15,14 @@
 	}
 	if(_fdinfo[d].oflags&O_APPEND)
 		_SEEK(d, 0, 2);
-	n = _WRITE(d, buf, nbytes);
+	n = _PWRITE(d, buf, nbytes, offset);
 	if(n < 0)
 		_syserrno();
 	return n;
 }
+
+ssize_t
+write(int d, const void *buf, size_t nbytes)
+{
+	return pwrite(d, buf, nbytes, -1LL);
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/posix/basename.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/posix/basename.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,21 @@
+#include <stdlib.h>
+#include <string.h>
+
+char *
+basename(char *path)
+{
+	int n;
+	char *p;
+
+	if(path == NULL || path[0] == '\0')
+		return ".";
+	n = strlen(path);
+	if(n == 1 && path[0] == '/' && path[1] == '\0')
+		return "/";
+	while(path[n-1] == '/')
+		path[--n] = '\0';
+	p = strrchr(path, '/');
+	if(p == NULL)
+		return path;
+	return p+1;
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/posix/dirname.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/posix/dirname.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,25 @@
+#include <stdlib.h>
+#include <string.h>
+
+char *
+dirname(char *path)
+{
+	int n;
+	char *p;
+
+	if(path == NULL || path[0] == '\0')
+		return ".";
+	n = strlen(path);
+	if(n == 1 && path[0] == '/' && path[1] == '\0')
+		return "/";
+	while(path[n-1] == '/')
+		path[--n] = '\0';
+	p = strrchr(path, '/');
+	if(p == NULL)
+		return ".";
+	while(*p == '/')
+		*p-- = '\0';
+	if(path[0] == '\0')
+		return "/";
+	return path;
+}
diff -r 02e3059af5bc sys/src/ape/lib/ap/posix/getpagesize.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/ap/posix/getpagesize.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,7 @@
+#include <unistd.h>
+
+int
+getpagesize(void)
+{
+	return sysconf(_SC_PAGESIZE);
+}
diff -r bfe93397b157 sys/src/ape/lib/ap/posix/mkfile
--- a/sys/src/ape/lib/ap/posix/mkfile	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/posix/mkfile	Fri Feb 12 10:59:32 2021 -0700
@@ -2,7 +2,10 @@
 <$APE/config
 LIB=/$objtype/lib/ape/libap.a
 OFILES=\
+	basename.$O\
+	dirname.$O\
 	getgrent.$O\
+	getpagesize.$O\
 	getpwent.$O\
 	locale.$O\
 	mkfifo.$O\
diff -r bfe93397b157 sys/src/ape/lib/ap/posix/sysconf.c
--- a/sys/src/ape/lib/ap/posix/sysconf.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/posix/sysconf.c	Fri Feb 12 10:59:32 2021 -0700
@@ -36,6 +36,8 @@
 		return _POSIX_VERSION;
 	case _SC_LOGIN_NAME_MAX:
 		return L_cuserid;
+	case _SC_PAGESIZE:
+		return 4096;
 	}
 	errno = EINVAL;
 	return -1;
diff -r bfe93397b157 sys/src/ape/lib/ap/stdio/_IO_putc.c
--- a/sys/src/ape/lib/ap/stdio/_IO_putc.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/stdio/_IO_putc.c	Fri Feb 12 10:59:32 2021 -0700
@@ -51,8 +51,13 @@
 				f->bufl+=BUFSIZ;
 				f->rp=t+f->bufl;
 			}else{
-				f->state=ERR;
-				return EOF;
+				/*
+				 * [v]snprintf should return number of characters
+				 * which would have written if enough space had enough available.
+				 * however sprintf is not.
+				 */
+				f->state=WR;
+				return c&0xff;
 			}
 		}
 		*f->wp++=c;
diff -r bfe93397b157 sys/src/ape/lib/ap/stdio/sclose.c
--- a/sys/src/ape/lib/ap/stdio/sclose.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/stdio/sclose.c	Fri Feb 12 10:59:32 2021 -0700
@@ -29,6 +29,8 @@
 					goto Error;
 				f->buf=t;
 				f->wp=t+f->bufl;
+			} else if(f->buf==NULL){
+				return NULL;
 			} else {
 				if(f->wp > f->buf)
 					*(f->wp-1) = '\0';
diff -r bfe93397b157 sys/src/ape/lib/ap/stdio/strerror.c
--- a/sys/src/ape/lib/ap/stdio/strerror.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/stdio/strerror.c	Fri Feb 12 10:59:32 2021 -0700
@@ -77,7 +77,17 @@

 	/* These added in 1003.1b-1993 */
 	"Operation canceled",
-	"Operation in progress"
+	"Operation in progress",
+
+	/* from research unix */
+	"Text file is busy",			/* ETXTBSY */
+
+	/* Added in more recent 1003.x versions */
+	"Operation already in progress",	/* EALREADY */
+	"Connection reset by peer",		/* ECONNRESET */
+
+	"Value too large for defined data type", /* EOVERFLOW */
+	"Too many symbolic links encountered",	/* ELOOP */
 };
 #define	_IO_nerr	(sizeof sys_errlist/sizeof sys_errlist[0])
 int sys_nerr = _IO_nerr;
diff -r bfe93397b157 sys/src/ape/lib/ap/stdio/vfprintf.c
--- a/sys/src/ape/lib/ap/stdio/vfprintf.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/ap/stdio/vfprintf.c	Fri Feb 12 10:59:32 2021 -0700
@@ -215,7 +215,7 @@
 		}
 		return -1;
 	}
-	return nprint;
+	return ferror(f) ? -1 : nprint;
 }

 static int
diff -r bfe93397b157 sys/src/ape/lib/bsd/arc4random.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/bsd/arc4random.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,30 @@
+#include <u.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <libsec.h>
+
+void
+arc4random_buf(void *buf, size_t nbytes)
+{
+	genrandom(buf, nbytes);
+}
+
+unsigned int
+arc4random(void)
+{
+	uint v;
+
+	arc4random_buf(&v, sizeof v);
+	return v;
+}
+
+int
+getentropy(void *buf, size_t len)
+{
+	if (len > 256) {
+		errno = EIO;
+		return -1;
+	}
+	genrandom(buf, len);
+	return 0;
+}
diff -r 8b4cfdf43705 sys/src/ape/lib/bsd/gethostname.c
--- a/sys/src/ape/lib/bsd/gethostname.c	Tue Feb 16 22:04:50 2021 +0100
+++ b/sys/src/ape/lib/bsd/gethostname.c	Tue Feb 16 21:43:40 2021 -0700
@@ -6,7 +6,7 @@
 #include <string.h>

 int
-gethostname(char *name, int namelen)
+gethostname(char *name, size_t namelen)
 {
 	int n, fd;
 	char buf[128];
diff -r bfe93397b157 sys/src/ape/lib/bsd/getprogname.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/bsd/getprogname.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,7 @@
+#include <lib9.h>
+
+const char *
+getprogname(void)
+{
+	return argv0;
+}
diff -r bfe93397b157 sys/src/ape/lib/bsd/mkfile
--- a/sys/src/ape/lib/bsd/mkfile	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/bsd/mkfile	Fri Feb 12 10:59:32 2021 -0700
@@ -4,6 +4,7 @@
 LIB=/$objtype/lib/ape/libbsd.a
 OFILES=\
 	accept.$O\
+	arc4random.$O\
 	bcopy.$O\
 	bind.$O\
 	connect.$O\
@@ -19,6 +20,7 @@
 	getopt.$O\
 	getpeername.$O\
 	getprotobyname.$O\
+	getprogname.$O\
 	getservbyaddr.$O\
 	getservbyname.$O\
 	getsockname.$O\
@@ -41,6 +43,7 @@
 	send.$O\
 	sendto.$O\
 	setlinebuf.$O\
+	setprogname.$O\
 	shutdown.$O\
 	_sock_ingetaddr.$O\
 	_sock_ipattr.$O\
diff -r bfe93397b157 sys/src/ape/lib/bsd/setprogname.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/bsd/setprogname.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,7 @@
+#include <lib9.h>
+
+void
+setprogname(const char *progname)
+{
+	argv0 = (char *)progname;
+}
diff -r bfe93397b157 sys/src/ape/lib/bsd/socket.c
--- a/sys/src/ape/lib/bsd/socket.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/ape/lib/bsd/socket.c	Fri Feb 12 10:59:32 2021 -0700
@@ -180,9 +180,23 @@
 /*
  * probably should do better than this
  */
-int getsockopt(int, int, int, void *, int *)
+int getsockopt(int fd, int level, int opt, void *v, int *len)
 {
-	return -1;
+	// should we check what fd is socket?
+	USED(fd, len);
+
+	if(level != SOL_SOCKET){
+		errno = ENOPROTOOPT;
+		return -1;
+	}
+	switch(opt){
+	case SO_ERROR:
+		*(int *)v = 0;
+		return 0;
+	default:
+		errno = EINVAL;
+		return -1;
+	}
 }

 int setsockopt(int, int, int, void *, int)
diff -r bfe93397b157 sys/src/ape/lib/pthread/_pthread.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/_pthread.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,83 @@
+#include <pthread.h>
+#include <string.h>
+#include "lib.h"
+
+static Lock privlock;
+static Thread privileges[PTHREAD_THREADS_MAX];
+
+Thread *
+_pthreadalloc(void)
+{
+	Thread *p, *ep;
+
+	ep = privileges+nelem(privileges);
+	lock(&privlock);
+	for(p = privileges; p < ep; p++){
+		if(!p->inuse){
+			memset(p, 0, sizeof(*p));
+			p->inuse = 1;
+			unlock(&privlock);
+			return p;
+		}
+	}
+	unlock(&privlock);
+	return NULL;
+}
+
+void
+_pthreadsetpid(Thread *priv, pthread_t pid)
+{
+	lock(&privlock);
+	priv->pid = pid;
+	unlock(&privlock);
+}
+
+Thread *
+_pthreadnew(pthread_t pid)
+{
+	Thread *p, *ep, *freep = NULL;
+
+	ep = privileges+nelem(privileges);
+	lock(&privlock);
+	for(p = privileges; p < ep; p++){
+		if(p->inuse && p->pid == pid){
+			unlock(&privlock);
+			return p;
+		}
+		if(freep == NULL && !p->inuse)
+			freep = p;
+	}
+	if(freep == NULL){
+		unlock(&privlock);
+		return NULL;
+	}
+	memset(freep, 0, sizeof(*freep));
+	freep->inuse = 1;
+	freep->pid = pid;
+	unlock(&privlock);
+	return freep;
+}
+
+Thread *
+_pthreadget(pthread_t pid)
+{
+	Thread *p, *ep;
+
+	ep = privileges+nelem(privileges);
+	lock(&privlock);
+	for(p = privileges; p < ep; p++)
+		if(p->inuse && p->pid == pid){
+			unlock(&privlock);
+			return p;
+		}
+	unlock(&privlock);
+	return NULL;
+}
+
+void
+_pthreadfree(Thread *priv)
+{
+	lock(&privlock);
+	priv->inuse = 0;
+	unlock(&privlock);
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/cond_broadcast.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/cond_broadcast.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,10 @@
+#include <pthread.h>
+
+int
+pthread_cond_broadcast(pthread_cond_t *cond)
+{
+	qlock(cond->r.l);
+	rwakeupall(&cond->r);
+	qunlock(cond->r.l);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/cond_destroy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/cond_destroy.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,8 @@
+#include <pthread.h>
+
+int
+pthread_cond_destroy(pthread_cond_t *)
+{
+	/* TODO: should we check cond is busy? */
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/cond_init.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/cond_init.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,10 @@
+#include <pthread.h>
+#include <string.h>
+
+int
+pthread_cond_init(pthread_cond_t *cond, pthread_condattr_t *)
+{
+	memset(cond, 0, sizeof(*cond));
+	cond->r.l = &cond->l;
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/cond_signal.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/cond_signal.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,10 @@
+#include <pthread.h>
+
+int
+pthread_cond_signal(pthread_cond_t *cond)
+{
+	qlock(cond->r.l);
+	rwakeup(&cond->r);
+	qunlock(cond->r.l);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/cond_wait.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/cond_wait.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,12 @@
+#include <pthread.h>
+
+int
+pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
+{
+	pthread_mutex_unlock(mutex);
+	qlock(cond->r.l);
+	rsleep(&cond->r);
+	qunlock(cond->r.l);
+	pthread_mutex_lock(mutex);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/create.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/create.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,37 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "lib.h"
+
+extern int	_RFORK(int);
+extern int	_RENDEZVOUS(unsigned long, unsigned long);
+
+int
+pthread_create(pthread_t *t, pthread_attr_t *attr, void *(*f)(void*),
void *arg)
+{
+	void *p;
+	int pid;
+	Thread *priv;
+	unsigned long tag;
+
+	if(attr != NULL)
+		return EINVAL;
+	priv = _pthreadalloc();
+	if(priv == NULL)
+		return EAGAIN;
+	tag = (unsigned long)priv;
+	pid = _RFORK(RFFDG|RFPROC|RFMEM);
+	switch(pid){
+	case -1:
+		_syserrno();
+		unlock(&priv->l);
+		_pthreadfree(priv);
+		return errno;
+	case 0:
+		_RENDEZVOUS(tag, 0);
+		p = f(arg);
+		pthread_exit(p);
+		abort(); /* can't reach here */
+	}
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/equal.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/equal.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,7 @@
+#include <pthread.h>
+
+int
+pthread_equal(pthread_t t1, pthread_t t2)
+{
+	return t1 == t2;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/exit.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/exit.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,21 @@
+#include <pthread.h>
+#include <assert.h>
+#include "lib.h"
+
+extern void	_EXITS(char *);
+
+void
+pthread_exit(void *retval)
+{
+	Thread *priv;
+	pthread_t pid;
+
+	pid = pthread_self();
+	priv = _pthreadget(pid);
+	assert(priv != NULL);
+	lock(&priv->l);
+	priv->exited = 1;
+	priv->ret = retval;
+	unlock(&priv->l);
+	_EXITS(0);
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/getspecific.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/getspecific.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,21 @@
+#include <pthread.h>
+#include "lib.h"
+
+void *
+pthread_getspecific(pthread_key_t key)
+{
+	int i;
+	pthread_t pid;
+	const void *p;
+
+	pid = pthread_self();
+	lock(&key.l);
+	for(i = 0; i < key.n; i++)
+		if(key.arenas[i].pid == pid){
+			p = key.arenas[i].p;
+			unlock(&key.l);
+			return (void *)p;
+		}
+	unlock(&key.l);
+	return NULL;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/join.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/join.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,100 @@
+#define _RESEARCH_SOURCE
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <libv.h>
+#include "lib.h"
+
+typedef
+struct Waitmsg
+{
+	int	pid;	/* of loved one */
+	ulong	time[3];	/* of loved one & descendants */
+	char	*msg;
+} Waitmsg;
+
+extern int	_AWAIT(char*, int);
+
+static Waitmsg*
+_wait(void)
+{
+	int n, l;
+	char buf[512], *fld[5];
+	Waitmsg *w;
+
+	n = _AWAIT(buf, sizeof buf-1);
+	if(n < 0){
+		_syserrno();
+		return nil;
+	}
+	buf[n] = '\0';
+	if(getfields(buf, fld, nelem(fld)) != nelem(fld)){
+		errno = ENOBUFS;
+		return nil;
+	}
+	l = strlen(fld[4])+1;
+	w = malloc(sizeof(Waitmsg)+l);
+	if(w == nil)
+		return nil;
+	w->pid = atoi(fld[0]);
+	w->time[0] = atoi(fld[1]);
+	w->time[1] = atoi(fld[2]);
+	w->time[2] = atoi(fld[3]);
+	w->msg = (char*)&w[1];
+	memmove(w->msg, fld[4], l);
+	return w;
+}
+
+static void
+emitexits(void **ret, Thread *priv)
+{
+	if(ret == NULL){
+		return;
+	}
+	*ret = priv->ret;
+}
+
+int
+pthread_join(pthread_t t, void **ret)
+{
+	static Lock l;
+	Thread *priv;
+	int pid;
+	Waitmsg *msg;
+
+	lock(&l);
+	priv = _pthreadget(t);
+	if(priv == NULL){
+		unlock(&l);
+		return EINVAL;
+	}
+	lock(&priv->l);
+	if(priv->exited){
+		emitexits(ret, priv);
+		unlock(&priv->l);
+		_pthreadfree(priv);
+		unlock(&l);
+		return 0;
+	}
+	unlock(&priv->l);
+
+	while((msg=_wait()) != NULL){
+		pid = msg->pid;
+		free(msg);
+		if(pid == t)
+			break;
+	}
+	lock(&priv->l);
+	if(priv->exited){
+		emitexits(ret, priv);
+		unlock(&priv->l);
+		_pthreadfree(priv);
+		unlock(&l);
+		return 0;
+	}
+	unlock(&priv->l);
+	unlock(&l);
+	return ESRCH;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/key_create.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/key_create.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,20 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "lib.h"
+
+int
+pthread_key_create(pthread_key_t *key, void (*destr_func)(void*))
+{
+	if(destr_func)
+		return EINVAL; /* don't implement yet */
+	memset(key, 0, sizeof(*key));
+	key->destroy = destr_func;
+	key->n = 32;
+	key->arenas = malloc(sizeof(*key->arenas)*key->n);
+	if(key->arenas == NULL)
+		return ENOMEM;
+	memset(key->arenas, 0, sizeof(*key->arenas)*key->n);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/key_delete.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/key_delete.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,10 @@
+#include <pthread.h>
+#include <stdlib.h>
+#include "lib.h"
+
+int
+pthread_key_delete(pthread_key_t key)
+{
+	free(key.arenas);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/lib.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/lib.h	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,48 @@
+#include <signal.h>
+
+#define nelem(a)	(sizeof(a)/sizeof((a)[0]))
+
+/* rfork */
+enum
+{
+	RFNAMEG		= (1<<0),
+	RFENVG		= (1<<1),
+	RFFDG		= (1<<2),
+	RFNOTEG		= (1<<3),
+	RFPROC		= (1<<4),
+	RFMEM		= (1<<5),
+	RFNOWAIT	= (1<<6),
+	RFCNAMEG	= (1<<10),
+	RFCENVG		= (1<<11),
+	RFCFDG		= (1<<12),
+	RFREND		= (1<<13),
+	RFNOMNT		= (1<<14)
+};
+
+typedef struct Thread Thread;
+struct Thread {
+	int		inuse;
+	pid_t		pid;
+
+	Lock		l;
+	int		exited;
+	void		*ret;
+	sigset_t	sigset;
+	int		state;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void	_syserrno(void);
+
+extern Thread*	_pthreadalloc(void);
+extern void	_pthreadsetpid(Thread*, pthread_t);
+extern Thread*	_pthreadnew(pthread_t);
+extern Thread*	_pthreadget(pthread_t);
+extern void	_pthreadfree(Thread*);
+
+#ifdef __cplusplus
+}
+#endif
diff -r bfe93397b157 sys/src/ape/lib/pthread/mkfile
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mkfile	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,36 @@
+APE=/sys/src/ape
+<$APE/config
+LIB=/$objtype/lib/ape/libpthread.a
+OFILES=\
+	_pthread.$O\
+	cond_broadcast.$O\
+	cond_destroy.$O\
+	cond_init.$O\
+	cond_signal.$O\
+	cond_wait.$O\
+	create.$O\
+	equal.$O\
+	exit.$O\
+	getspecific.$O\
+	join.$O\
+	key_create.$O\
+	key_delete.$O\
+	mutexattr_destroy.$O\
+	mutexattr_init.$O\
+	mutexattr_settype.$O\
+	mutex_destroy.$O\
+	mutex_init.$O\
+	mutex_lock.$O\
+	mutex_trylock.$O\
+	mutex_unlock.$O\
+	once.$O\
+	self.$O\
+	setcancelstate.$O\
+	setspecific.$O\
+	sigmask.$O\
+
+HFILES=lib.h
+
+</sys/src/cmd/mksyslib
+
+CFLAGS=-c -D_POSIX_SOURCE -FTVw -D_SUSV2_SOURCE -D_PLAN9_SOURCE
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutex_destroy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutex_destroy.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,8 @@
+#include <pthread.h>
+
+int
+pthread_mutex_destroy(pthread_mutex_t *)
+{
+	/* TODO: should we check mutex is busy? */
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutex_init.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutex_init.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,11 @@
+#include <pthread.h>
+#include <string.h>
+
+int
+pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
+{
+	memset(mutex, 0, sizeof(*mutex));
+	if(attr)
+		mutex->attr = *attr;
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutex_lock.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutex_lock.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,23 @@
+#include <pthread.h>
+
+int
+pthread_mutex_lock(pthread_mutex_t *mutex)
+{
+	pthread_t pid;
+
+	pid = pthread_self();
+	lock(&mutex->mu);
+	if(mutex->attr == PTHREAD_MUTEX_RECURSIVE && mutex->pid == pid){
+		mutex->ref++;
+		unlock(&mutex->mu);
+		return 0;
+	}
+	unlock(&mutex->mu);
+
+	qlock(&mutex->l);
+	lock(&mutex->mu);
+	mutex->pid = pid;
+	mutex->ref++;
+	unlock(&mutex->mu);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutex_trylock.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutex_trylock.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,25 @@
+#include <pthread.h>
+#include <errno.h>
+
+int
+pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+	pthread_t pid;
+
+	pid = pthread_self();
+	lock(&mutex->mu);
+	if(mutex->attr == PTHREAD_MUTEX_RECURSIVE && mutex->pid == pid){
+		mutex->ref++;
+		unlock(&mutex->mu);
+		return 0;
+	}
+	unlock(&mutex->mu);
+
+	if(!canqlock(&mutex->l))
+		return EBUSY;
+	lock(&mutex->mu);
+	mutex->pid = pid;
+	mutex->ref++;
+	unlock(&mutex->mu);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutex_unlock.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutex_unlock.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,29 @@
+#include <pthread.h>
+#include <errno.h>
+
+int
+pthread_mutex_unlock(pthread_mutex_t *mutex)
+{
+	pthread_t pid;
+
+	pid = pthread_self();
+	lock(&mutex->mu);
+	if(mutex->pid != pid){
+		unlock(&mutex->mu);
+		return EPERM;
+	}
+	if(mutex->attr == PTHREAD_MUTEX_RECURSIVE){
+		mutex->ref--;
+		if(mutex->ref <= 0){
+			mutex->pid = 0;
+			mutex->ref = 0;
+			qunlock(&mutex->l);
+		}
+		unlock(&mutex->mu);
+		return 0;
+	}
+	mutex->ref--;
+	qunlock(&mutex->l);
+	unlock(&mutex->mu);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutexattr_destroy.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutexattr_destroy.c	Fri Feb 12 10:59:32 2021
-0700
@@ -0,0 +1,7 @@
+#include <pthread.h>
+
+int
+pthread_mutexattr_destroy(pthread_mutexattr_t*)
+{
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutexattr_init.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutexattr_init.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,8 @@
+#include <pthread.h>
+
+int
+pthread_mutexattr_init(pthread_mutexattr_t *attr)
+{
+	*attr = 0;
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/mutexattr_settype.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/mutexattr_settype.c	Fri Feb 12 10:59:32 2021
-0700
@@ -0,0 +1,8 @@
+#include <pthread.h>
+
+int
+pthread_mutexattr_settype(pthread_mutexattr_t *attr, int kind)
+{
+	*attr = kind;
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/once.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/once.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,13 @@
+#include <pthread.h>
+
+int
+pthread_once(pthread_once_t *once_control, void (*init_routine) (void))
+{
+	lock(&once_control->l);
+	if(once_control->once == 0){
+		init_routine();
+		once_control->once++;
+	}
+	unlock(&once_control->l);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/self.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/self.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,8 @@
+#include <pthread.h>
+#include <unistd.h>
+
+pthread_t
+pthread_self(void)
+{
+	return getpid();
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/setcancelstate.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/setcancelstate.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,21 @@
+#include <pthread.h>
+#include <errno.h>
+#include "lib.h"
+
+int
+pthread_setcancelstate(int state, int *oldstate)
+{
+	Thread *priv;
+	pthread_t pid;
+
+	pid = pthread_self();
+	priv = _pthreadnew(pid);
+	if(priv == NULL)
+		return ENOMEM;
+	lock(&priv->l);
+	if(oldstate)
+		*oldstate = priv->state;
+	priv->state = state;
+	unlock(&priv->l);
+	return 0;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/setspecific.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/setspecific.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,30 @@
+#include <pthread.h>
+#include <errno.h>
+#include "lib.h"
+
+int
+pthread_setspecific(pthread_key_t key, const void *p)
+{
+	int i;
+	pthread_t pid;
+
+	pid = pthread_self();
+	lock(&key.l);
+	/* exactly match */
+	for(i = 0; i < key.n; i++)
+		if(key.arenas[i].pid == pid){
+			key.arenas[i].p = p;
+			unlock(&key.l);
+			return 0;
+		}
+	/* unused */
+	for(i = 0; i < key.n; i++)
+		if(key.arenas[i].pid == 0){
+			key.arenas[i].pid = pid;
+			key.arenas[i].p = p;
+			unlock(&key.l);
+			return 0;
+		}
+	unlock(&key.l);
+	return ENOMEM;
+}
diff -r bfe93397b157 sys/src/ape/lib/pthread/sigmask.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/src/ape/lib/pthread/sigmask.c	Fri Feb 12 10:59:32 2021 -0700
@@ -0,0 +1,21 @@
+#include <pthread.h>
+#include <errno.h>
+#include "lib.h"
+
+int
+pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset)
+{
+	Thread *priv;
+	pthread_t pid;
+
+	pid = pthread_self();
+	priv = _pthreadnew(pid);
+	if(priv == NULL)
+		return ENOMEM;
+	lock(&priv->l);
+	if(oldset)
+		*oldset = priv->sigset;
+	priv->sigset = *set;
+	unlock(&priv->l);
+	return 0;
+}
diff -r bfe93397b157 sys/src/cmd/cpp/cpp.c
--- a/sys/src/cmd/cpp/cpp.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/cmd/cpp/cpp.c	Fri Feb 12 10:59:32 2021 -0700
@@ -238,7 +238,12 @@
 		break;

 	case KINCLUDE:
-		doinclude(trp);
+		doinclude(trp, 0);
+		trp->lp = trp->bp;
+		return;
+
+	case KINCLUDE_NEXT:
+		doinclude(trp, 1);
 		trp->lp = trp->bp;
 		return;

diff -r bfe93397b157 sys/src/cmd/cpp/cpp.h
--- a/sys/src/cmd/cpp/cpp.h	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/cmd/cpp/cpp.h	Fri Feb 12 10:59:32 2021 -0700
@@ -19,8 +19,8 @@
 		ASRSH, ASOR, ASAND, ELLIPS,
 		DSHARP1, NAME1, DEFINED, UMINUS, MAXTOK};

-enum kwtype { KIF, KIFDEF, KIFNDEF, KELIF, KELSE, KENDIF, KINCLUDE, KDEFINE,
-		KUNDEF, KLINE, KERROR, KWARNING, KPRAGMA, KDEFINED,
+enum kwtype { KIF, KIFDEF, KIFNDEF, KELIF, KELSE, KENDIF, KINCLUDE,
KINCLUDE_NEXT,
+		KDEFINE, KUNDEF, KLINE, KERROR, KWARNING, KPRAGMA, KDEFINED,
 		KLINENO, KFILE, KDATE, KTIME, KSTDC, KEVAL };

 #define	ISDEFINED	01	/* has #defined value */
@@ -60,6 +60,7 @@
 	int	fd;		/* input source */
 	int	ifdepth;	/* conditional nesting in include */
 	struct	source *next;	/* stack for #include */
+	int	pos;		/* next position for #include_next */
 } Source;

 typedef struct nlist {
@@ -105,7 +106,7 @@
 void	control(Tokenrow *);
 void	dodefine(Tokenrow *);
 void	doadefine(Tokenrow *, int);
-void	doinclude(Tokenrow *);
+void	doinclude(Tokenrow *, int);
 void	doif(Tokenrow *, enum kwtype);
 void	expand(Tokenrow *, Nlist *);
 void	builtin(Tokenrow *, int);
diff -r bfe93397b157 sys/src/cmd/cpp/include.c
--- a/sys/src/cmd/cpp/include.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/cmd/cpp/include.c	Fri Feb 12 10:59:32 2021 -0700
@@ -6,12 +6,21 @@

 char	*objname;

+static int
+curpos(int next)
+{
+	if (next)
+		return cursource->pos;
+	return NINCLUDE;
+}
+
 void
-doinclude(Tokenrow *trp)
+doinclude(Tokenrow *trp, int next)
 {
 	char fname[256], iname[256], *p;
 	Includelist *ip;
-	int angled, len, fd, i;
+	Source *s;
+	int angled, len, fd, i, pos;

 	trp->tp += 1;
 	if (trp->tp>=trp->lp)
@@ -44,6 +53,7 @@
 	if (trp->tp < trp->lp || len==0)
 		goto syntax;
 	fname[len] = '\0';
+	pos = NINCLUDE;
 	if (fname[0]=='/') {
 		fd = open(fname, 0);
 		strcpy(iname, fname);
@@ -59,7 +69,7 @@
 				fd = open(iname, 0);
 			}
 		}
-		for (i=NINCLUDE-1; fd<0 && i>=0; i--) {
+		for (i=curpos(next)-1; fd<0 && i>=0; i--) {
 			ip = &includelist[i];
 			if (ip->file==NULL || ip->deleted || (angled && ip->always==0))
 				continue;
@@ -68,9 +78,12 @@
 			strcpy(iname, ip->file);
 			strcat(iname, "/");
 			strcat(iname, fname);
-			fd = open(iname, 0);
+			if((fd = open(iname, 0)) >= 0){
+				pos = i;
+				break;
+			}
 		}
-		if (fd<0 && angled) {
+		if (fd<0 && angled && !next) {
 			strcpy(iname, cursource->filename);
 			p = strrchr(iname, '/');
 			if(p != NULL) {
@@ -78,6 +91,7 @@
 				strcat(iname, "/");
 				strcat(iname, fname);
 				fd = open(iname, 0);
+				pos = NINCLUDE-1;
 			}
 		}
 	}
@@ -89,7 +103,8 @@
 	if (fd >= 0) {
 		if (++incdepth > 20)
 			error(FATAL, "#include too deeply nested");
-		setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd, NULL);
+		s = setsource((char*)newstring((uchar*)iname, strlen(iname), 0), fd,
NULL);
+		s->pos = pos;
 		genline();
 	} else {
 		trp->tp = trp->bp+2;
diff -r bfe93397b157 sys/src/cmd/cpp/lex.c
--- a/sys/src/cmd/cpp/lex.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/cmd/cpp/lex.c	Fri Feb 12 10:59:32 2021 -0700
@@ -538,6 +538,7 @@
 	s->inp = s->inb;
 	s->inl = s->inp+len;
 	s->inl[0] = s->inl[1] = s->inl[2] = s->inl[3] = EOFC;
+	s->pos = NINCLUDE; /* outside of include dirs */
 	return s;
 }

diff -r bfe93397b157 sys/src/cmd/cpp/nlist.c
--- a/sys/src/cmd/cpp/nlist.c	Wed Sep 16 20:45:49 2020 +0000
+++ b/sys/src/cmd/cpp/nlist.c	Fri Feb 12 10:59:32 2021 -0700
@@ -28,6 +28,7 @@
 	"else",		KELSE,		ISKW,
 	"endif",	KENDIF,		ISKW,
 	"include",	KINCLUDE,	ISKW,
+	"include_next",	KINCLUDE_NEXT,	ISKW,	// extension to ANSI
 	"define",	KDEFINE,	ISKW,
 	"undef",	KUNDEF,		ISKW,
 	"line",		KLINE,		ISKW,
diff -r 3540943c10e8 sys/src/cmd/python/pyconfig.h
--- a/sys/src/cmd/python/pyconfig.h	Thu Feb 18 15:13:25 2021 +0100
+++ b/sys/src/cmd/python/pyconfig.h	Thu Feb 18 15:23:05 2021 -0700
@@ -46,7 +46,7 @@

 #define SIGWINCH 21	/* for curses */

-#define S_ISSOCK S_ISFIFO /* for hg, see /sys/include/ape/sys/stat.h */
+/* #define S_ISSOCK S_ISFIFO for hg, see /sys/include/ape/sys/stat.h */

 /* Define if --enable-ipv6 is specified */
 #define ENABLE_IPV6 1




             reply	other threads:[~2021-02-22  2:56 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-22  2:48 bsdsm [this message]
2021-02-22  4:14 ` ori
2021-02-22  5:20   ` Jens Staal
2021-02-25  2:15 ` ori
2021-02-25  2:21   ` ori
2021-02-25 16:37     ` Aaron
2021-02-25 18:06       ` ori
2021-02-26 10:28         ` cinap_lenrek
2021-02-26 15:38           ` Lucas Francesco
2021-02-26 19:23 ` [9front] " bsdsm
2021-03-01  3:41   ` ori
2021-03-15  3:20   ` ori
2021-03-15  3:36   ` ori

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0e170f2c1818fb21b795c2151e52adaf.squirrel@mx.sdf.org \
    --to=bsdsm@sdf.org \
    --cc=9front@9front.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).