Goto sanos source index

//
// stdlib.c
//
// Standard library functions
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright 
//    notice, this list of conditions and the following disclaimer.  
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.  
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
// SUCH DAMAGE.
// 

#include <os.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <inifile.h>

#define SHELL "sh.exe"

static long holdrand = 1L;
static int serial = -1;

typedef void (__cdecl *proc_t)(void);

static proc_t *atexit_begin = NULL;
static proc_t *atexit_end = NULL;
static proc_t *atexit_last = NULL;

#pragma function(abs)
#pragma function(labs)

int atexit(proc_t exitfunc) {
  if (atexit_end == atexit_last) {
    int size = atexit_end - atexit_begin;
    int newsize = size + 32;
    atexit_begin = (proc_t *) realloc(atexit_begin, newsize * sizeof(proc_t));
    if (atexit_begin == NULL) return -ENOMEM;
    atexit_end = atexit_begin + size;
    atexit_last = atexit_begin + newsize;
  }

  *atexit_end++ = exitfunc;
  return 0;
}

void run_atexit_handlers() {
  if (atexit_begin) {
    while (--atexit_end >= atexit_begin) if (*atexit_end != NULL) (**atexit_end)();
    free(atexit_begin);
    atexit_begin = atexit_end = atexit_last = NULL;
  }
}

void abort() {
  raise(SIGABRT);
#ifdef __GNUC__
  while (1);
#endif
}

int abs(int number) {
  return number >= 0 ? number : -number;
}

div_t div(int numer, int denom) {
  div_t result;

  result.quot = numer / denom;
  result.rem  = numer - (result.quot * denom);

  if (numer < 0 && result.rem > 0) {
    result.quot++;
    result.rem -= denom;
  }

  return result;
}

long labs(long n) {
  return  n >= 0L ? n : -n;
}

ldiv_t ldiv(long numer, long denom) {
  ldiv_t result;

  result.quot = numer / denom;
  result.rem = numer % denom;

  if (numer < 0 && result.rem > 0) {
    result.quot++;
    result.rem -= denom;
  }

  return result;
}

void srand(unsigned int seed) {
  holdrand = (long) seed;
}

int rand() {
  return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}

int system(const char *command) {
  char *cmdline;
  int cmdlen;
  int rc;

  if (!command) {
    errno = EINVAL;
    return -1;
  }

  cmdlen = strlen(SHELL) + 1 + strlen(command);
  cmdline = malloc(cmdlen + 1);
  if (!cmdline) {
    errno = ENOMEM;
    return -1;
  }

  strcpy(cmdline, SHELL);
  strcat(cmdline, " ");
  strcat(cmdline, command);

  rc = spawn(P_WAIT, SHELL, cmdline, NULL, NULL);
  free(cmdline);
  return rc;
}

char *realpath(const char *path, char *resolved) {
  int rc;
  char *buffer = NULL;

  if (!resolved) resolved = buffer = malloc(MAXPATH);
  rc = canonicalize(path, resolved, MAXPATH);
  if (rc < 0) {
    resolved = NULL;
    if (buffer) free(buffer);
  }
  return resolved;
}

char *basename(char *path) {
  char *p;

  if (!path || !*path) return ".";
  p = path + strlen(path) - 1;
  while (p > path && (*p == PS1 || *p == PS2)) *p-- = '\0';
  if (p != path) {
    while (p > path && p[-1] != PS1 && p[-1] != PS2) p--;
  }
  return p;
}

char *dirname(char *path) {
  char *p;
  
  if (!path || !*path) return ".";
  p = path + strlen(path) - 1;
  while (p > path && (*p == PS1 || *p == PS2)) p--;
  while (p > path && *p != PS1 && *p != PS2) p--;
  while (p > path && (*p == PS1 || *p == PS2)) p--;
  if (p == path && *p != PS1 && *p != PS2) return ".";
  p[1] = '\0';
  return path;
}

char *mktemp(char *template) {
  char *begin;
  char *end;

  // Initialize serial number to pid
  if (serial == -1) serial = getpid();

  // Find range of Xs in template
  begin = NULL;
  for (end = template; *end; end++) {
    if (*end == 'X') {
      if (!begin) begin = end;
    } else {
      begin = NULL;
    }
  }
  if (!begin) {
    errno = EINVAL;
    return NULL;
  } else {
    // Keep trying new serial numbers
    for (;;) {
      // Insert serial number in template
      int id = serial++;
      char *p = end;
      while (p > begin) {
        *--p = (id % 10) + '0';
        id /= 10;
      }

      // Test if file exists
      if (access(template, 0) < 0 && errno == ENOENT) break;
      if (errno != EEXIST) {
        return NULL;
        break;
      }
    }
  }
  return template;
}

char *mkdtemp(char *template) {
  char *begin;
  char *end;

  // Initialize serial number to pid
  if (serial == -1) serial = getpid();

  // Find range of Xs in template
  begin = NULL;
  for (end = template; *end; end++) {
    if (*end == 'X') {
      if (!begin) begin = end;
    } else {
      begin = NULL;
    }
  }
  if (!begin) {
    errno = EINVAL;
    return NULL;
  } else {
    // Keep trying new serial numbers
    for (;;) {
      // Insert serial number in template
      int id = serial++;
      char *p = end;
      while (p > begin) {
        *--p = (id % 10) + '0';
        id /= 10;
      }

      // Test if directory exists
      if (mkdir(template, 0700) == 0) break;
      if (errno != EEXIST) {
        return NULL;
        break;
      }
    }
  }
  return template;
}

int mkstemps(char *template, int suffixlen) {
  char *begin;
  char *end;
  char *suffix;
  int fd;

  // Initialize serial number to pid
  if (serial == -1) serial = getpid();

  // Find suffix start
  suffix = template;
  while (*suffix) suffix++;
  suffix -= suffixlen;

  // Find range of Xs in template
  begin = NULL;
  for (end = template; end < suffix; end++) {
    if (*end == 'X') {
      if (!begin) begin = end;
    } else {
      begin = NULL;
    }
  }
  if (!begin) {
    errno = EINVAL;
    return -1;
  }

  // Keep trying new serial numbers
  for (;;) {
    // Insert serial number in template
    int id = serial++;
    char *p = end;
    while (p > begin) {
      *--p = (id % 10) + '0';
      id /= 10;
    }

    // Test if file exists
    fd = open(template, O_CREAT | O_EXCL | O_RDWR, 0600);
    if (fd >= 0) return fd;
    if (errno != EEXIST) return -1;
  }
  return -1;
}

int mkstemp(char *template) {
  return mkstemps(template, 0);
}

int getpagesize() {
  static int pagesize = 0;
  if (pagesize == 0) {
    struct meminfo mem;
    if (sysinfo(SYSINFO_MEM, &mem, sizeof(mem)) < 0) return PAGESIZE;
    pagesize = mem.pagesize;
  }

  return pagesize;
}

int getrusage(int who, struct rusage *usage) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

char *setlocale(int category, const char *locale) {
  // TODO implement
  return NULL;
}

struct lconv *localeconv(void) {
  //  TODO implement
  return NULL;
}

int symlink(const char *oldpath, const char *newpath) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

int readlink(const char *name, char *buf, size_t size) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

int chroot(const char *path) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

int flock(handle_t f, int operation) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

int lockf(handle_t f, int func, off_t size) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}

int fcntl(handle_t f, int cmd, ...) {
  // TODO implement
  errno = ENOSYS;
  return -1;
}