libposix: initial draft
This commit is contained in:
parent
e70feee4a3
commit
188a07782d
@ -25,6 +25,8 @@ typedef int32_t pid_t;
|
|||||||
typedef uint32_t Rune;
|
typedef uint32_t Rune;
|
||||||
typedef union FPdbleword FPdbleword;
|
typedef union FPdbleword FPdbleword;
|
||||||
typedef uintptr jmp_buf[10]; // for registers.
|
typedef uintptr jmp_buf[10]; // for registers.
|
||||||
|
typedef long off_t;
|
||||||
|
typedef long ptrdiff_t;
|
||||||
|
|
||||||
#define JMPBUFSP 6
|
#define JMPBUFSP 6
|
||||||
#define JMPBUFPC 7
|
#define JMPBUFPC 7
|
||||||
|
2
hacking
2
hacking
@ -1 +1 @@
|
|||||||
Subproject commit b1ab4f1a08b9b7156ecb4034527bfc87e159186e
|
Subproject commit eb37bc6013a49cf27600b5b3df9fbc598971bf34
|
152
sys/include/posix.h
Normal file
152
sys/include/posix.h
Normal 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
2
sys/posix/newlib/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
@ -22,6 +22,7 @@
|
|||||||
"/sys/src/lib/mp/",
|
"/sys/src/lib/mp/",
|
||||||
"/sys/src/lib/ndb/",
|
"/sys/src/lib/ndb/",
|
||||||
"/sys/src/lib/plumb/",
|
"/sys/src/lib/plumb/",
|
||||||
|
"/sys/src/lib/posix/",
|
||||||
"/sys/src/lib/regexp/",
|
"/sys/src/lib/regexp/",
|
||||||
"/sys/src/lib/sec/",
|
"/sys/src/lib/sec/",
|
||||||
"/sys/src/lib/stdio/",
|
"/sys/src/lib/stdio/",
|
||||||
|
4
sys/src/lib/posix/.gitignore
vendored
Normal file
4
sys/src/lib/posix/.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
libc.h
|
||||||
|
libc_wrapper.h
|
||||||
|
*.a
|
||||||
|
libc.sed
|
22
sys/src/lib/posix/build.json
Normal file
22
sys/src/lib/posix/build.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
158
sys/src/lib/posix/environment.c
Normal file
158
sys/src/lib/posix/environment.c
Normal 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
159
sys/src/lib/posix/errors.c
Normal 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
301
sys/src/lib/posix/files.c
Normal 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;
|
||||||
|
}
|
63
sys/src/lib/posix/initlib.c
Normal file
63
sys/src/lib/posix/initlib.c
Normal 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;
|
||||||
|
}
|
29
sys/src/lib/posix/internal.h
Normal file
29
sys/src/lib/posix/internal.h
Normal 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);
|
90
sys/src/lib/posix/memory.c
Normal file
90
sys/src/lib/posix/memory.c
Normal 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);
|
||||||
|
}
|
56
sys/src/lib/posix/others.c
Normal file
56
sys/src/lib/posix/others.c
Normal 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;
|
||||||
|
}
|
194
sys/src/lib/posix/processes.c
Normal file
194
sys/src/lib/posix/processes.c
Normal 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");
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user