libposix: initial draft

This commit is contained in:
Giacomo Tesio 2017-04-19 23:48:54 +02:00
parent e70feee4a3
commit 188a07782d
15 changed files with 1234 additions and 1 deletions

View File

@ -25,6 +25,8 @@ typedef int32_t pid_t;
typedef uint32_t Rune;
typedef union FPdbleword FPdbleword;
typedef uintptr jmp_buf[10]; // for registers.
typedef long off_t;
typedef long ptrdiff_t;
#define JMPBUFSP 6
#define JMPBUFPC 7

@ -1 +1 @@
Subproject commit b1ab4f1a08b9b7156ecb4034527bfc87e159186e
Subproject commit eb37bc6013a49cf27600b5b3df9fbc598971bf34

152
sys/include/posix.h Normal file
View File

@ -0,0 +1,152 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* Jehanne is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* This API is designed to help porting other POSIX compliant C
* libraries (such as newlib or musl) to Jehanne, so that they can be
* used to port further software.
*
* POSIX_* functions provide a facade between the Jehanne's libc and
* the POSIX 1-2008 semantics.
*
* libposix_* functions provide the configuration point.
*
* #include <u.h>
* #include <posix.h>
*/
typedef unsigned long clock_t;
#define __POSIX_EXIT_PREFIX "posix error "
#define __POSIX_SIGNAL_PREFIX "posix: "
extern void POSIX_exit(int code) __attribute__((noreturn));
extern int POSIX_close(int *errnop, int file);
extern int POSIX_execve(int *errnop, const char *name, char * const*argv, char * const*env);
extern int POSIX_fork(int *errnop);
extern int POSIX_fstat(int *errnop, int file, void *stat);
extern int POSIX_getpid(int *errnop);
extern int POSIX_isatty(int *errnop, int file);
extern int POSIX_kill(int *errnop, int pid, int sig);
extern int POSIX_link(int *errnop, const char *old, const char *new);
extern off_t POSIX_lseek(int *errnop, int fd, off_t pos, int whence);
extern int POSIX_open(int *errnop, const char *name, int flags, int mode);
extern long POSIX_read(int *errnop, int fd, char *buf, size_t len);
extern int POSIX_stat(int *errnop, const char *file, void *stat);
extern clock_t POSIX_times(int *errnop, void *tms);
extern int POSIX_unlink(int *errnop, const char *name);
extern int POSIX_wait(int *errnop, int *status);
extern long POSIX_write(int *errnop, int fd, const void *buf, size_t len);
extern int POSIX_gettimeofday(int *errnop, void *timeval, void *timezone);
extern char* POSIX_getenv(int *errnop, const char *name);
extern void *POSIX_sbrk(int *errnop, ptrdiff_t incr);
extern void * POSIX_malloc(int *errnop, size_t size);
extern void *POSIX_realloc(int *errnop, void *ptr, size_t size);
extern void *POSIX_calloc(int *errnop, size_t nelem, size_t size);
extern void POSIX_free(void *ptr);
/* Library initialization
*/
#define _ERRNO_H // skip the Posix part, we just need the enum
#include <apw/errno.h>
/* Initialize libposix. Should call
*
* libposix_define_errno to set the value of each PosixError
* libposix_translate_error to translate error strings to PosixError
* libposix_set_stat_reader
* libposix_set_tms_reader
* libposix_set_timeval_reader
* libposix_set_timezone_reader
*/
typedef void (*PosixInit)(void);
extern void libposix_init(int argc, char *argv[], PosixInit init) __attribute__((noreturn));
/* Translate an error string to a PosixError, in the context of the
* calling function (typically a pointer to a POSIX_* function).
*
* Must return 0 if unable to identify a PosixError.
*
* Translators are tried in reverse registration order.
*/
typedef PosixError (*PosixErrorTranslator)(char* error, uintptr_t caller);
/* Register a translation between Jehanne error strings and PosixErrors.
* If caller is not zero, it is a pointer to the calling
* functions to consider. Otherwise the translation will be tried whenever
* for any caller, after the specialized ones.
*/
extern int libposix_translate_error(PosixErrorTranslator translation, uintptr_t caller);
/* define the value of a specific PosixError according to the library headers */
extern int libposix_define_errno(PosixError e, int errno);
/* Map a Dir to the stat structure expected by the library.
*
* Must return 0 on success or a PosixError on failure.
*/
typedef PosixError (*PosixStatReader)(void *statp, const Dir *dir);
extern int libposix_set_stat_reader(PosixStatReader reader);
/* Map a time provided by times() tms structure
* expected by the library.
*
* Must return 0 on success or a PosixError on failure.
*/
typedef PosixError (*PosixTMSReader)(void *tms,
unsigned int proc_userms, unsigned int proc_sysms,
unsigned int children_userms, unsigned int children_sysms);
extern int libposix_set_tms_reader(PosixTMSReader reader);
/* Map a time provided by gmtime() or localtime() to a timeval
* expected by the library.
*
* Must return 0 on success or a PosixError on failure.
*/
typedef PosixError (*PosixTimevalReader)(void *timeval, const Tm *time);
extern int libposix_set_timeval_reader(PosixTimevalReader reader);
/* Map a time provided by gmtime() or localtime() to a timezone
* expected by the library.
*
* Must return 0 on success or a PosixError on failure.
*/
typedef PosixError (*PosixTimezoneReader)(void *timezone, const Tm *time);
extern int libposix_set_timezone_reader(PosixTimezoneReader reader);
/* Map the POSIX_open flag and mode to Jehanne's arguments to open
* or create.
*
* omode is a pointer to the open/create omode argument
* cperm is a pointer to the create perm argument that must be filled
* only if O_CREATE has been set in mode.
*
* Must return 0 on success or a PosixError on failure.
*/
typedef PosixError (*PosixOpenTranslator)(int flag, int mode, long *omode, long *cperm);
extern int libposix_translate_open(PosixOpenTranslator translation);
extern int libposix_translate_seek_whence(int seek_set, int seek_cur, int seek_end);
typedef int (*PosixSignalTrampoline)(int signal);
extern int libposix_set_signal_trampoline(PosixSignalTrampoline trampoline);

2
sys/posix/newlib/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -22,6 +22,7 @@
"/sys/src/lib/mp/",
"/sys/src/lib/ndb/",
"/sys/src/lib/plumb/",
"/sys/src/lib/posix/",
"/sys/src/lib/regexp/",
"/sys/src/lib/sec/",
"/sys/src/lib/stdio/",

4
sys/src/lib/posix/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
libc.h
libc_wrapper.h
*.a
libc.sed

View File

@ -0,0 +1,22 @@
{
"LibPosix": {
"Cflags": [
"-fasm",
"-I."
],
"Include": [
"../lib.json"
],
"Install": "/arch/$ARCH/lib/",
"Library": "libposix.a",
"SourceFiles": [
"environment.c",
"errors.c",
"files.c",
"initlib.c",
"memory.c",
"others.c",
"processes.c"
]
}
}

View File

@ -0,0 +1,158 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
static char* __env[1] = { nil };
char **environ = &__env[0]; /* how to map this to #e? */
/* In POSIX, getenv returns strings that must not be freed by the caller.
* In Jehanne (and Plan9) getenv returns strings obtained with malloc().
*
* Thus we need a more complex managememnt to avoid that calling
* getenv("PATH") several times would leak memory.
*
* We use a sorted linked list of outputs returned by Jehanne's getenv
* and search it before actually calling it.
*/
#define MAX_ENVNAME_LEN (127+5+1)
typedef struct EnvVar EnvVar;
struct EnvVar
{
char* name;
char* value;
EnvVar* next;
};
static RWLock list_lock;
static EnvVar* list_start;
static void
free_env(EnvVar* e)
{
free(e->name);
free(e->value);
free(e);
}
static void
put_in_list(EnvVar* newenv)
{
int cmp;
EnvVar *e, **o;
wlock(&list_lock);
e = list_start;
o = &list_start;
while(e != nil){
cmp = strcmp(e->name, newenv->name);
if(cmp < 0){
// check next (alphabetically sorted)
o = &e->next;
e = e->next;
} else {
if(cmp > 0){
// reached the next variable
newenv->next = e;
} else {
// found the variable to replace
newenv->next = e->next;
free_env(e);
}
e = nil; // quit the lookup
}
}
*o = newenv;
wunlock(&list_lock);
}
char *
POSIX_getenv(int *errno, const char *name)
{
EnvVar* e;
if(name == nil || name[0] == 0 || strchr(name, '=') == nil){
*errno = PosixEINVAL;
return nil;
}
rlock(&list_lock);
e = list_start;
while(e != nil){
if(strcmp(name, e->name) == 0)
break;
e = e->next;
}
runlock(&list_lock);
if(e != nil)
return e->value;
e = malloc(sizeof(EnvVar));
e->next = nil;
e->value = nil; // see free_env
e->name = strdup(name);
if(e->name == nil){
free_env(e);
*errno = PosixENOMEM;
return nil;
}
e->value = getenv(name);
if(e->value == nil){
free_env(e);
return nil;
}
put_in_list(e);
return e->value;
}
void
__libposix_setup_exec_environment(char * const *env)
{
int fd, len;
char **e, *start, *end;
char ename[MAX_ENVNAME_LEN];
if(env == nil || env[0] == nil)
return;
strcpy(ename, "#e/");
for(e = (char **)env; (start = *e); e++) {
end = strchr(start, '=');
if(!end || start==end)
continue; /* not in "var=val" format */
len = end-start;
if(len > 127)
len = 127;
memcpy(ename+3, start, len);
ename[3+len] = 0;
fd = ocreate(ename, OWRITE, 0666);
if(fd < 0)
continue;
end++; /* after '=' */
len = strlen(end);
sys_pwrite(fd, end, len, -1);
sys_close(fd);
}
}

159
sys/src/lib/posix/errors.c Normal file
View File

@ -0,0 +1,159 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
int *__libposix_errors_codes;
typedef struct PosixErrorMap PosixErrorMap;
struct PosixErrorMap
{
PosixErrorTranslator translate;
PosixErrorMap *next;
};
typedef struct CustomErrorMap CustomErrorMap;
struct CustomErrorMap
{
uintptr_t caller;
PosixErrorMap *head;
CustomErrorMap *next;
};
static PosixErrorMap *generic_handlers;
static CustomErrorMap *custom_handlers;
void
__libposix_errors_check_conf(void)
{
int i;
/* check that all required configurations has been provided */
for(i = 0; i < ERRNO_LAST-ERRNO_FIRST; ++i){
if(__libposix_errors_codes[i] == 0)
sysfatal("libposix: PosixError %d is undefined", i + ERRNO_FIRST);
}
if(generic_handlers == nil)
sysfatal("libposix: no generic error handler");
}
int
libposix_define_errno(PosixError e, int errno)
{
if(e < ERRNO_FIRST || e > ERRNO_LAST)
return 0;
__libposix_errors_codes[e - ERRNO_FIRST] = errno;
return 1;
}
static int
register_translation(PosixErrorMap **map, PosixErrorTranslator translation)
{
PosixErrorMap *entry = malloc(sizeof(PosixErrorMap));
if(entry == nil)
return 0;
entry->translate = translation;
entry->next = *map;
*map = entry;
return 1;
}
int
libposix_translate_error(PosixErrorTranslator translation, uintptr_t caller)
{
CustomErrorMap **list = nil;
if(__libposix_initialized())
return 0;
if(translation == nil)
return 0;
if(caller == 0)
return register_translation(&generic_handlers, translation);
list = &custom_handlers;
while(*list != nil)
{
if((*list)->caller == caller)
break;
list = &(*list)->next;
}
if(*list == nil){
*list = malloc(sizeof(CustomErrorMap));
(*list)->next = nil;
(*list)->caller = caller;
(*list)->head = nil;
}
return register_translation(&(*list)->head, translation);
}
int
__libposix_get_errno(PosixError e)
{
if(e == 0)
return 0;
if(e < 0){
/* this way we allow a translator to return a
* non-posix errno as a negative number that will not
* collide with the indexes declared in PosixError enum
*/
return (int)-e;
}
if(e < ERRNO_FIRST || e > ERRNO_LAST)
return PosixEINVAL;
return __libposix_errors_codes[e - ERRNO_FIRST];
}
static PosixError
get_posix_error(PosixErrorMap *translations, char *err, uintptr_t caller)
{
PosixError e = 0;
while(translations != nil)
{
e = translations->translate(err, caller);
if(e != 0)
return e;
translations = translations->next;
}
return PosixEINVAL;
}
int
__libposix_translate_errstr(uintptr_t caller)
{
CustomErrorMap *handler;
PosixError perr = 0;
char err[ERRMAX];
int ret;
if(sys_errstr(err, ERRMAX) < 0)
return __libposix_get_errno(PosixEINVAL);
handler = custom_handlers;
while(handler != nil)
{
if(handler->caller == caller)
break;
}
if(handler != nil)
perr = get_posix_error(handler->head, err, caller);
if(perr == 0)
perr = get_posix_error(generic_handlers, err, caller);
ret = __libposix_get_errno(perr);
sys_errstr(err, ERRMAX);
return ret;
}

301
sys/src/lib/posix/files.c Normal file
View File

@ -0,0 +1,301 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
static PosixStatReader __libposix_stat_reader;
static PosixOpenTranslator __libposix_open_translation;
typedef enum SeekTypes
{
SeekSet = 0,
SeekCurrent = 1,
SeekEnd = 2
} SeekTypes;
static int *__libposix_seek_types;
void
__libposix_files_check_conf(void)
{
if(__libposix_stat_reader == nil)
sysfatal("libposix: no stat reader");
if(__libposix_open_translation == nil)
sysfatal("libposix: no open translator");
if(__libposix_seek_types == nil)
sysfatal("libposix: no seek translations");
}
int
libposix_translate_open(PosixOpenTranslator translation)
{
if(__libposix_initialized())
return 0;
if(translation == nil)
return 0;
__libposix_open_translation = translation;
return 1;
}
int
libposix_set_stat_reader(PosixStatReader reader)
{
if(__libposix_initialized())
return 0;
if(reader == nil)
return 0;
__libposix_stat_reader = reader;
return 1;
}
int
libposix_translate_seek_whence(int seek_set, int seek_cur, int seek_end)
{
if(__libposix_initialized())
return 0;
if(seek_set == seek_cur)
return 0;
if(seek_set == seek_end)
return 0;
if(seek_cur == seek_end)
return 0;
__libposix_seek_types = malloc(sizeof(int)*3);
if(__libposix_seek_types == nil)
return 0;
__libposix_seek_types[SeekSet] = seek_set;
__libposix_seek_types[SeekCurrent] = seek_cur;
__libposix_seek_types[SeekEnd] = seek_end;
return 1;
}
static SeekTypes
find_seek_type(int whence)
{
if(__libposix_seek_types[SeekSet] == whence)
return SeekSet;
if(__libposix_seek_types[SeekCurrent] == whence)
return SeekCurrent;
if(__libposix_seek_types[SeekEnd] == whence)
return SeekEnd;
return -1;
}
int
POSIX_open(int *errnop, const char *name, int flags, int mode)
{
long omode = 0, cperm = 0;
PosixError e;
int f;
if(name == nil){
*errnop = __libposix_get_errno(PosixENOENT);
return -1;
}
e = __libposix_open_translation(flags, mode, &omode, &cperm);
if(e != 0){
*errnop = __libposix_get_errno(e);
return -1;
}
if(cperm == 0){
f = sys_open(name, omode);
} else {
f = ocreate(name, (unsigned int)omode, (unsigned int)cperm);
}
if(f >= 0)
return f;
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_open);
return -1;
}
long
POSIX_read(int *errnop, int fd, char *buf, size_t len)
{
long r;
if(fd < 0){
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
}
r = sys_pread(fd, buf, len, -1);
if(r < 0){
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_read);
return -1;
}
return r;
}
long
POSIX_write(int *errnop, int fd, const void *buf, size_t len)
{
long w;
if(fd < 0){
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
}
w = sys_pwrite(fd, buf, len, -1);
if(w < 0){
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_write);
return -1;
}
return w;
}
off_t
POSIX_lseek(int *errnop, int fd, off_t pos, int whence)
{
SeekTypes stype;
long r;
stype = find_seek_type(whence);
if(stype == -1){
*errnop = __libposix_get_errno(PosixEINVAL);
return -1;
}
if(fd < 0){
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
}
r = sys_seek(fd, pos, stype);
if(r >= 0)
return r;
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_lseek);
return -1;
}
int
POSIX_close(int *errno, int file)
{
long ret;
ret = sys_close(file);
switch(ret){
case 0:
return 0;
case ~0:
*errno = __libposix_translate_errstr((uintptr_t)POSIX_close);
break;
default:
*errno = ret;
break;
}
return -1;
}
int
POSIX_link(int *errnop, const char *old, const char *new)
{
int err;
/* let choose the most appropriate error */
if(old == nil || new == nil || old[0] == 0 || new[0] == 0)
err = __libposix_get_errno(PosixENOENT);
else if(access(new, AEXIST) == 0)
err = __libposix_get_errno(PosixEEXIST);
else if(access(old, AEXIST) == 0)
err = __libposix_get_errno(PosixENOENT);
else {
/* Jehanne does not support links.
* A custom overlay filesystem might support them in
* the future but so far it does not exists yet.
*
* We return EXDEV so that a posix compliant caller
* can fallback to a simple copy.
*/
err = __libposix_get_errno(PosixEXDEV);
}
*errnop = err;
return -1;
}
int
POSIX_unlink(int *errnop, const char *name)
{
long ret;
if(name == nil || name[0] == 0){
*errnop = __libposix_get_errno(PosixENOENT);
return -1;
}
ret = sys_remove(name);
switch(ret){
case 0:
return 0;
case ~0:
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_unlink);
break;
default:
*errnop = ret;
break;
}
return -1;
}
int
POSIX_fstat(int *errnop, int file, void *pstat)
{
Dir *d;
PosixError e;
if(pstat == nil){
*errnop = __libposix_get_errno(PosixEOVERFLOW);
return -1;
}
if(file < 0){
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
}
d = dirfstat(file);
if(d == nil)
{
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_fstat);
return -1;
}
e = __libposix_stat_reader(pstat, d);
free(d);
if(e == 0)
return 0;
*errnop = __libposix_get_errno(e);
return -1;
}
int
POSIX_stat(int *errnop, const char *file, void *pstat)
{
Dir *d;
PosixError e;
if(pstat == nil){
*errnop = __libposix_get_errno(PosixEOVERFLOW);
return -1;
}
if(file == nil){
*errnop = __libposix_get_errno(PosixEBADF);
return -1;
}
d = dirstat(file);
if(d == nil)
{
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_stat);
return -1;
}
e = __libposix_stat_reader(pstat, d);
free(d);
if(e == 0)
return 0;
*errnop = __libposix_get_errno(e);
return -1;
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
extern int *__libposix_errors_codes;
static int __initialized;
static void
libposix_check_configuration(void)
{
__libposix_errors_check_conf();
__libposix_files_check_conf();
__libposix_processes_check_conf();
}
void
libposix_init(int argc, char *argv[], PosixInit init)
{
extern int main(int, char**);
int error_codes[ERRNO_LAST-ERRNO_FIRST];
int status;
assert(__initialized == 0);
/* initialize PosixErrors map */
memset(error_codes, 0, sizeof(error_codes));
__libposix_errors_codes=error_codes;
if(!atnotify(__libposix_note_handler, 1))
sysfatal("libposix: atnotify");
init();
libposix_check_configuration();
__initialized = 1;
status = main(argc, argv);
POSIX_exit(status);
}
int
__libposix_initialized(void)
{
return __initialized;
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
extern void __libposix_files_check_conf(void);
extern void __libposix_errors_check_conf(void);
extern void __libposix_processes_check_conf(void);
extern int __libposix_initialized(void);
extern int __libposix_get_errno(PosixError e);
extern void __libposix_setup_exec_environment(char * const *env);
extern int __libposix_translate_errstr(uintptr_t caller);
extern int __libposix_note_handler(void *ureg, char *note);

View File

@ -0,0 +1,90 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
void *
POSIX_sbrk(int *errnop, ptrdiff_t incr)
{
void *p;
p = segbrk(incr);
if(p != (void*)-1)
return p;
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_sbrk);
return (void*)-1;
}
void *
POSIX_malloc(int *errnop, size_t size)
{
void *p;
p = malloc(size);
if(p != nil)
return p;
*errnop = __libposix_get_errno(PosixENOMEM);
return nil;
}
void *
POSIX_realloc(int *errnop, void *ptr, size_t size)
{
void *p;
p = realloc(ptr, size);
if(p != nil)
return p;
if(size == 0){
if(ptr != nil){
// POSIX 1-2008 requires an "implementation defined" errno
*errnop = __libposix_get_errno(PosixEINVAL);
}
} else {
*errnop = __libposix_get_errno(PosixENOMEM);
}
return nil;
}
void *
POSIX_calloc(int *errnop, size_t nelem, size_t size)
{
void *p;
size = size * nelem;
if(size <= 0){
// POSIX 1-2008 requires an "implementation defined" errno
*errnop = __libposix_get_errno(PosixEINVAL);
return nil;
}
p = malloc(size);
if(p != nil){
memset(p, 0, size);
return p;
}
*errnop = __libposix_get_errno(PosixENOMEM);
return nil;
}
void
POSIX_free(void *ptr)
{
jehanne_free(ptr);
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
int
POSIX_isatty(int *errnop, int fd)
{
char buf[64];
int l;
if(fd < 0){
*errnop = __libposix_get_errno(PosixEBADF);
return 0;
}
if(sys_fd2path(fd, buf, sizeof(buf)) < 0){
*errnop = __libposix_get_errno(PosixENOTTY);
return 0;
}
l = strlen(buf);
if(l >= 9 && strcmp(buf+l-9, "/dev/cons") == 0)
return 1;
*errnop = __libposix_get_errno(PosixENOTTY);
return 0;
}
clock_t
POSIX_times(int *errnop, void *buf)
{
*errnop = __libposix_get_errno(PosixEINVAL);
return -1;
}
int
POSIX_gettimeofday(int *errnop, void *timeval, void *timezone)
{
*errnop = __libposix_get_errno(PosixEINVAL);
return -1;
}

View File

@ -0,0 +1,194 @@
/*
* This file is part of Jehanne.
*
* Copyright (C) 2017 Giacomo Tesio <giacomo@tesio.it>
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, version 3 of the License.
*
* Jehanne is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Jehanne. If not, see <http://www.gnu.org/licenses/>.
*/
#include <u.h>
#include <lib9.h>
#include <posix.h>
#include "internal.h"
extern char **environ;
static PosixSignalTrampoline __libposix_signal_trampoline;
#define __POSIX_SIGNAL_PREFIX_LEN (sizeof(__POSIX_SIGNAL_PREFIX)-1)
void
POSIX_exit(int code)
{
char buf[64];
if(code == 0)
exits(nil);
snprint(buf, sizeof(buf), __POSIX_EXIT_PREFIX "%d", code);
exits(buf);
}
int
POSIX_execve(int *errnop, const char *name, char * const*argv, char * const*env)
{
long ret;
// see http://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html
if(env == environ){
/* just get a copy of the current environment */
sys_rfork(RFENVG);
} else {
sys_rfork(RFCENVG);
__libposix_setup_exec_environment(env);
}
ret = sys_exec(name, argv);
switch(ret){
case 0:
return 0;
case ~0:
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_execve);
break;
default:
*errnop = ret;
break;
}
return -1;
}
int
POSIX_wait(int *errnop, int *status)
{
Waitmsg *w;
char *s;
int ret = 0, pid;
w = wait();
if(w == nil){
*errnop = __libposix_get_errno(PosixECHILD);
return -1;
}
pid = w->pid;
if(w->msg[0] != 0){
s = strstr(w->msg, __POSIX_EXIT_PREFIX);
if(s){
s += (sizeof(__POSIX_EXIT_PREFIX)/sizeof(char) - 1);
ret = atoi(s);
} else {
/* TODO: setup configurable interpretations */
ret = 127;
}
}
if(status != nil)
*status = ret;
free(w);
return pid;
}
static int
note_all_writable_processes(int *errnop, char *note)
{
// TODO: loop over writable note files and post note.
*errnop = __libposix_get_errno(PosixEPERM);
return -1;
}
int
POSIX_kill(int *errnop, int pid, int sig)
{
char msg[64], file[128];
int mode;
int ret;
if(access("/proc", AEXEC) != 0){
*errnop = __libposix_get_errno(PosixEPERM);
return -1;
}
snprint(msg, sizeof(msg), __POSIX_SIGNAL_PREFIX "%d", sig);
switch(pid){
case 0:
mode = PNGROUP;
break;
case -1:
return note_all_writable_processes(errnop, msg);
default:
if(pid < 0){
mode = PNGROUP;
pid = -pid;
} else {
mode = PNPROC;
}
}
snprint(file, sizeof(file), "/proc/%d/note", pid);
if(access(file, AWRITE) != 0){
if(access(file, AEXIST) == 0)
*errnop = __libposix_get_errno(PosixEPERM);
else
*errnop = __libposix_get_errno(PosixESRCH);
return -1;
}
ret = postnote(mode, pid, msg);
if(ret != 0){
*errnop = __libposix_translate_errstr((uintptr_t)POSIX_kill);
return -1;
}
return 0;
}
int
POSIX_getpid(int *errnop)
{
return getpid();
}
int
POSIX_fork(int *errnop)
{
return fork();
}
static int
translate_jehanne_note(char *note)
{
// TODO: implement
return 0;
}
int
__libposix_note_handler(void *ureg, char *note)
{
int sig;
if(strncmp(note, __POSIX_SIGNAL_PREFIX, __POSIX_SIGNAL_PREFIX_LEN) != 0)
return translate_jehanne_note(note); // TODO: should we translate common notes?
sig = atoi(note+__POSIX_SIGNAL_PREFIX_LEN);
return __libposix_signal_trampoline(sig);
}
int
libposix_set_signal_trampoline(PosixSignalTrampoline trampoline)
{
if(__libposix_initialized())
return 0;
if(trampoline == nil)
return 0;
__libposix_signal_trampoline = trampoline;
return 1;
}
void
__libposix_processes_check_conf(void)
{
if(__libposix_signal_trampoline == nil)
sysfatal("libposix: no signal trampoline");
}