Usermode/libc - Improved strerror, added some basic time functions
authorJohn Hodge <[email protected]>
Sat, 27 Jul 2013 10:23:26 +0000 (18:23 +0800)
committerJohn Hodge <[email protected]>
Sat, 27 Jul 2013 10:23:26 +0000 (18:23 +0800)
Usermode/Libraries/libc.so_src/Makefile
Usermode/Libraries/libc.so_src/env.c
Usermode/Libraries/libc.so_src/errno.c
Usermode/Libraries/libc.so_src/include_exp/errno.enum.h [changed mode: 0644->0755]
Usermode/Libraries/libc.so_src/include_exp/signal.h
Usermode/Libraries/libc.so_src/include_exp/stdlib.h
Usermode/Libraries/libc.so_src/perror.c
Usermode/Libraries/libc.so_src/signals.c
Usermode/Libraries/libc.so_src/stub.c
Usermode/Libraries/libc.so_src/time.c

index c8f4e5d..7b34587 100644 (file)
@@ -4,7 +4,7 @@
 -include ../Makefile.cfg\r
 \r
 CPPFLAGS += \r
-CFLAGS   += -Werror -Wextra\r
+CFLAGS   += -Wall -Werror -Wextra\r
 ASFLAGS  +=\r
 LDFLAGS  += -Map map.txt\r
 \r
index b38e279..e1b5d81 100644 (file)
@@ -4,31 +4,93 @@
 */
 #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;
+}
+
index b5fe958..af369b1 100644 (file)
@@ -17,20 +17,38 @@ EXPORT int *libc_geterrno()
 
 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)
old mode 100644 (file)
new mode 100755 (executable)
index 831ab65..be953d4
@@ -1,5 +1,5 @@
 
-enum {
+enum libc_eErrorNumbers {
        EOK,
        ENOSYS, // Invalid Instruction
        EINVAL, // Invalid Paramater
@@ -9,7 +9,7 @@ enum {
        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
@@ -22,14 +22,14 @@ enum {
        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)
 
index c2d03e1..e25db03 100644 (file)
@@ -36,10 +36,43 @@ extern int  raise(int sig);
 #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
 
index bbf76eb..2bfb00d 100644 (file)
@@ -76,6 +76,7 @@ extern long long int  llabs(long long int j);
 \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
index 0431635..53c01f8 100644 (file)
@@ -7,8 +7,11 @@
  */
 #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));
 }
index c33019e..5e32fc8 100644 (file)
@@ -6,20 +6,22 @@
 #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;
 }
 
@@ -41,3 +43,30 @@ void abort(void)
        // 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;
+}
index f723d54..e20deae 100644 (file)
@@ -28,7 +28,7 @@ extern void   _stdio_init(void);
 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
@@ -46,7 +46,7 @@ tCPUID        gCPU_Features;
 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
index aa4b2de..412475b 100644 (file)
@@ -7,6 +7,7 @@
  */
 #include <time.h>
 #include <acess/sys.h>
+#include <string.h>
 
 clock_t clock(void)
 {
@@ -20,3 +21,71 @@ time_t time(time_t *t)
                *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;
+}

UCC git Repository :: git.ucc.asn.au