-include ../Makefile.cfg\r
\r
CPPFLAGS += \r
-CFLAGS += -Werror -Wextra\r
+CFLAGS += -Wall -Werror -Wextra\r
ASFLAGS +=\r
LDFLAGS += -Map map.txt\r
\r
*/
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
// === GLOBALS ===
-char **_envp = NULL;
+char **environ = NULL;
+static char **expected_environ = NULL;
+static int num_allocated_slots;
// === CODE ===
char *getenv(const char *name)
{
- char **env;
char *env_str;
int len;
- if(!_envp) return NULL;
+ if(!environ) return NULL;
if(!name) return NULL;
len = strlen((char*)name);
- env = _envp;
- while(*env)
+ for( char **env = environ; *env; env ++ )
{
env_str = *env;
if(strncmp(name, env_str, len) == 0 && env_str[len] == '=') {
return env_str+len+1;
}
- env ++;
}
return NULL;
}
+
+
+int putenv(char *string)
+{
+ char *eqpos = strchr(string, '=');
+ if( !eqpos ) {
+ errno = EINVAL;
+ return -1;
+ }
+ size_t namelen = eqpos - string;
+
+ static const int alloc_step = 10;
+ if( expected_environ == NULL || expected_environ != environ )
+ {
+ if( expected_environ )
+ free(expected_environ);
+
+ int envc = 0;
+ // Take a copy
+ for( char **env = environ; *env; env ++ )
+ envc ++;
+ envc ++; // NULL termination
+ envc ++; // assume we're adding a new value
+
+ num_allocated_slots = (envc + alloc_step-1) / alloc_step * alloc_step;
+
+ expected_environ = malloc(num_allocated_slots*sizeof(char*));
+ if(!expected_environ)
+ return 1;
+
+ int idx = 0;
+ for( char **env = environ; *env; env ++ )
+ expected_environ[idx++] = *env;
+ expected_environ[idx++] = NULL;
+
+ environ = expected_environ;
+ }
+
+ int envc = 0;
+ for( char **env = environ; *env; env ++, envc++ )
+ {
+ if( strncmp(*env, string, namelen) != 0 )
+ continue ;
+ if( *env[namelen] != '=' )
+ continue ;
+ *env = string;
+ return 0;
+ }
+ if( num_allocated_slots >= envc+1 )
+ {
+ num_allocated_slots += alloc_step;
+ expected_environ = realloc(expected_environ, num_allocated_slots*sizeof(char*));
+ if(!expected_environ)
+ return 1;
+ environ = expected_environ;
+ }
+ environ[envc] = string;
+ environ[envc+1] = NULL;
+
+ return 0;
+}
+
EXPORT char *strerror(int errnum)
{
- switch(errnum)
+ switch((enum libc_eErrorNumbers)errnum)
{
case EOK: return "Success";
- case EISDIR: return "Is a directory";
- case ENOTDIR: return "Not a directory";
case ENOSYS: return "Invalid instruction/syscall";
+ case EINVAL: return "Bad argument(s)";
+ case EBADF: return "Invalid file";
+ case ENOMEM: return "No free memory";
+ case EACCES: return "Not permitted";
+ case EBUSY: return "Resource is busy";
+ case ERANGE: return "Value out of range";
+ case ENOTFOUND: return "Item not found";
+ case EROFS: return "Read only filesystem";
+ case ENOTIMPL: return "Not implimented";
case ENOENT: return "No such file or directory";
- case EINVAL: return "Bad arguments";
- case EPERM: return "Permissions error";
- default:
- _SysDebug("strerror: errnum=%i unk", errnum);
- errno = EINVAL;
- return "unknown error";
+ case EEXIST: return "Already exists";
+ case ENFILE: return "Too many open files";
+ case ENOTDIR: return "Not a directory";
+ case EISDIR: return "Is a directory";
+ case EIO: return "IO Error";
+ case EINTR: return "Interrupted";
+ case EWOULDBLOCK: return "Operation would have blocked";
+ case ENODEV: return "No such device";
+ case EADDRNOTAVAIL: return "Address not avaliable";
+ case EINPROGRESS: return "Operation in process";
+ case EPERM: return "Operation not permitted";
+ case EAGAIN: return "Try again";
+ case EALREADY: return "Operation was no-op";
+ case EINTERNAL: return "Internal error";
}
+ _SysDebug("strerror: errnum=%i unk", errnum);
+ errno = EINVAL;
+ return "unknown error";
}
EXPORT int strerror_r(int errnum, char *buf, size_t bufsiz)
-enum {
+enum libc_eErrorNumbers {
EOK,
ENOSYS, // Invalid Instruction
EINVAL, // Invalid Paramater
EBUSY, // Resource is busy
ERANGE, // Value out of range
ENOTFOUND, // Item not found
- EREADONLY, // Read only (duplicate with EROFS?)
+ EROFS, // Read only
ENOTIMPL, // Not implemented
ENOENT, // No entry?
EEXIST, // Already exists
ENODEV, // ???
EADDRNOTAVAIL, // ?
EINPROGRESS, // ?
- EROFS,
EPERM, // Permissions error
EAGAIN, // Try again
-
EALREADY, // Operation was a NOP
- EINTERNAL, // Internal Error
- NUM_ERRNO
+
+ EINTERNAL // Internal Error
};
+
+#define NUM_ERRNO (EINTERNAL+1)
#define SIGUSR1 16
#define SIGUSR2 17
-#define SIGPIPE 1001
-#define SIGCHLD 1002
+#define SIGSTOP 30 // Stop process
+#define SIGTSTP 31 // ? ^Z
+#define SIGTTIN 32 // Background process read TTY
+#define SIGTTOU 33 // Background process write TTY
+#define SIGPIPE 34
+#define SIGCHLD 35
+#define SIGWINCH 36
-typedef int sigset_t;
+typedef long long unsigned int sigset_t;
+extern int sigemptyset(sigset_t *set);
+extern int sigfillset(sigset_t *set);
+
+typedef struct siginfo_s siginfo_t;
+
+struct siginfo_s
+{
+ int si_signo;
+ int si_errno;
+ int si_code;
+ int si_trapno;
+ pid_t si_pid;
+ uid_t si_uid;
+ int si_status;
+ // TODO: There's others
+};
+
+struct sigaction
+{
+ sighandler_t sa_handler;
+ //void (*sa_sigaction)(int, siginfo_t *, void *);
+ sigset_t sa_mask;
+ int sa_flags;
+};
+
+#define SA_NOCLDSTOP 0x001
+
+extern int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
#endif
\r
/* --- Environment --- */\r
extern char *getenv(const char *name);\r
+extern int putenv(char *string);\r
\r
/* --- Search/Sort --- */\r
typedef int (*_stdlib_compar_t)(const void *, const void *);\r
*/
#include <errno.h>
#include <stdio.h>
+#include <acess/sys.h>
void perror(const char *s)
{
- fprintf(stderr, "%s: Error (%i)\n", s, errno);
+ int errnum = errno;
+ _SysDebug("perror(): %s: Error (%i) %s", s, errnum, strerror(errnum));
+ fprintf(stderr, "%s: Error (%i) %s\n", s, errnum, strerror(errnum));
}
#include <stdlib.h>
#include <signal.h>
#include "lib.h"
+#include <errno.h>
// === CONSTANTS ===
-#define NUM_SIGNALS 32
+#define NUM_SIGNALS 40
// === GLOBALS ===
-sighandler_t sighandlers[NUM_SIGNALS];
+struct sigaction sighandlers[NUM_SIGNALS];
// === CODE ===
sighandler_t signal(int num, sighandler_t handler)
{
sighandler_t prev;
if(num < 0 || num >= NUM_SIGNALS) return NULL;
- prev = sighandlers[num];
- sighandlers[num] = handler;
+ prev = sighandlers[num].sa_handler;
+ sighandlers[num].sa_handler = handler;
+ sighandlers[num].sa_mask = 0;
return prev;
}
// raise(SIGABRT);
_exit(-1);
}
+
+// POSIX
+int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact)
+{
+ if( signum < 0 || signum >= NUM_SIGNALS ) {
+ errno = EINVAL;
+ return 1;
+ }
+
+ if( oldact )
+ *oldact = sighandlers[signum];
+ if( act )
+ sighandlers[signum] = *act;
+
+ return 0;
+}
+
+int sigemptyset(sigset_t *set)
+{
+ *set = 0;
+ return 0;
+}
+int sigfillset(sigset_t *set)
+{
+ *set = -1;
+ return 0;
+}
extern void _call_atexit_handlers(void);\r
\r
// === GLOBALS ===\r
-extern char **_envp;\r
+extern char **environ;\r
// --- CPU Features ---\r
#if USE_CPUID\r
tCPUID gCPU_Features;\r
int SoMain(UNUSED(uintptr_t, BaseAddress), UNUSED(int, argc), UNUSED(char **, argv), char **envp)\r
{\r
// Init for env.c\r
- _envp = envp;\r
+ environ = envp;\r
\r
#if 0 \r
{\r
*/
#include <time.h>
#include <acess/sys.h>
+#include <string.h>
clock_t clock(void)
{
*t = ret;
return ret;
}
+
+static struct tm static_tm;
+
+struct tm *localtime(const time_t *timer)
+{
+ struct tm *ret = &static_tm;
+
+ // TODO: This breaks on negative timestamps
+
+ int64_t day = *timer / (1000*60*60*24);
+ int64_t iday = *timer % (1000*60*60*24);
+
+ ret->tm_sec = (iday / 1000) % 60;;
+ ret->tm_min = (iday / (1000*60)) % 60;
+ ret->tm_hour = (iday / (1000*60*60));
+ ret->tm_year = 0;
+ ret->tm_mon = 0;
+ ret->tm_mday = 0;
+ ret->tm_wday = (day + 6) % 7; // 1 Jan 2000 was a saturday
+ ret->tm_yday = 0;
+ ret->tm_isdst = 0; // Fuck DST
+ return ret;
+}
+
+static inline size_t MIN(size_t a, size_t b) { return a < b ? a : b; }
+static size_t _puts(char * restrict s, size_t maxsize, size_t ofs, const char *str, size_t len)
+{
+ if( s && ofs < maxsize ) {
+ size_t addlen = MIN(len, maxsize-1-ofs);
+ memcpy(s+ofs, str, addlen);
+ }
+ return len;
+}
+
+size_t strftime(char*restrict s, size_t maxsize, const char*restrict format, const struct tm*restrict timeptr)
+{
+ size_t ofs = 0;
+
+ while( *format )
+ {
+ const char *restrict start = format;
+ while( *format && *format != '%' )
+ format ++;
+ if( format != start )
+ ofs += _puts(s, maxsize, ofs, start, format-start);
+ if( *format == 0 )
+ break;
+ format ++;
+ switch(*format++)
+ {
+ case 0: format--; break;
+ case '%': ofs += _puts(s, maxsize, ofs, format-1, 1); break;
+ case 'd': // The day of the month as a decimal number (range 01 to 31).
+ {
+ char tmp[2] = {'0','0'};
+ tmp[0] += (timeptr->tm_mday / 10) % 10;
+ tmp[1] += timeptr->tm_mday % 10;
+ ofs += _puts(s, maxsize, ofs, tmp, 2);
+ }
+ break;
+ default:
+ _SysDebug("TODO: strftime('...%%%c...')", format[-1]);
+ break;
+ }
+ }
+
+ return ofs;
+}