Goto sanos source index
//
// msvcrt.c
//
// C runtime library
//
// 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 "msvcrt.h"
int _adjust_fdiv = 0;
int __mb_cur_max = 1;
int _app_type = _UNKNOWN_APP;
int _error_mode;
char **__initenv = NULL;
int _commode = _IOCOMMIT;
static long holdrand = 1L;
//int _fltused = 0x9875;
int _sys_nerr = 90;
#if _MSC_VER >= 1400
#pragma function(wcslen)
#pragma function(wcscpy)
#pragma function(wcscat)
#pragma function(wcscmp)
#endif
void _initterm(_PVFV *begin, _PVFV *end) {
TRACE("_initterm");
while (begin < end)
{
if (*begin != NULL) (**begin)();
++begin;
}
}
char ***__p___initenv() {
TRACE("__p___initenv");
return &__initenv;
}
int *__p__commode() {
TRACE("__p__commode");
return &_commode;
}
int *__p__fmode() {
TRACE("__p__fmode");
return &fmode;
}
void __set_app_type(int type) {
TRACE("__set_app_type");
_app_type = type;
}
void __setusermatherr(int (*errhandler)(struct _exception *)) {
TRACE("__setusermatherr");
syslog(LOG_DEBUG, "warning: __setusermatherr not implemented, ignored");
}
int _XcptFilter(unsigned long xcptnum, void *pxcptinfoptrs) {
syslog(LOG_ERR, "Exception %d catched in MSVCRT", xcptnum);
return 0;
}
void _cexit() {
TRACE("_cexit");
syslog(LOG_DEBUG, "warning: _cexit not implemented, ignored");
}
void _c_exit() {
TRACE("_c_exit");
syslog(LOG_DEBUG, "warning: _c_exit not implemented, ignored");
}
void _amsg_exit(int rterrnum) {
TRACE("_amsg_exit");
syslog(LOG_DEBUG, "warning: _amsg_exit(%d) not implemented, ignored", rterrnum);
}
_onexit_t __dllonexit(_onexit_t func, _PVFV **pbegin, _PVFV **pend) {
TRACE("__dllonexit");
//syslog(LOG_DEBUG, "warning: __dllonexit not implemented, ignored");
return func;
}
_onexit_t __cdecl _onexit(_onexit_t func) {
TRACE("_onexit");
syslog(LOG_DEBUG, "warning: _onexit not implemented, ignored");
return func;
}
static int parse_args(char *args, char **argv) {
char *p;
int argc;
char *start;
char *end;
char *buf;
int delim;
p = args;
argc = 0;
while (*p) {
while (*p == ' ') p++;
if (!*p) break;
if (*p == '"' || *p == '\'') {
delim = *p++;
start = p;
while (*p && *p != delim) p++;
end = p;
if (*p == delim) p++;
} else {
start = p;
while (*p && *p != ' ') p++;
end = p;
}
if (argv) {
buf = (char *) malloc(end - start + 1);
if (!buf) break;
memcpy(buf, start, end - start);
buf[end - start] = 0;
argv[argc] = buf;
}
argc++;
}
return argc;
}
static char **build_env_block() {
struct section *env = find_section(osconfig(), "env");
struct property *prop;
int num = 0;
char **envp;
if (env) {
prop = env->properties;
while (prop) {
num++;
prop = prop->next;
}
}
envp = malloc(sizeof(char *) * (num + 1));
if (!envp) return NULL;
if (env) {
num = 0;
prop = env->properties;
while (prop) {
int len = strlen(prop->name);
if (prop->value) len += strlen(prop->value) + 1;
envp[num] = malloc(len + 1);
if (!envp[num]) return NULL;
strcpy(envp[num], prop->name);
if (prop->value) {
strcpy(envp[num] + strlen(envp[num]), "=");
strcpy(envp[num] + strlen(envp[num]), prop->value);
}
num++;
prop = prop->next;
}
}
envp[num] = NULL;
return envp;
}
void __getmainargs(int *pargc, char ***pargv, char ***penvp, int dowildcard, _startupinfo *startinfo) {
TRACE("__getmainargs");
// TODO: argv and envp should be freed on termination
*pargc = parse_args(gettib()->proc->cmdline, NULL);
*pargv = malloc(sizeof(char *) * *pargc);
if (*pargv) parse_args(gettib()->proc->cmdline, *pargv);
*penvp = build_env_block();
}
time_t _time(time_t *timer) {
time_t t;
TRACE("_time");
t = time(timer);
return t;
}
int printf(const char *fmt, ...) {
va_list args;
int n;
char buffer[1024];
TRACE("printf");
va_start(args, fmt);
n = vsprintf(buffer, fmt, args);
va_end(args);
return write(1, buffer, n);
}
int _vsnprintf(char *buffer, size_t size, const char *fmt, va_list args) {
int n;
TRACE("_vsnprintf");
// TODO: check buffer length
n = vsprintf(buffer, fmt, args);
if (n >= (int) size) panic("vsnprintf: overflow");
return n;
}
int _snprintf(char *buffer, size_t size, const char *fmt, ...) {
va_list args;
int n;
TRACE("_snprintf");
va_start(args, fmt);
n = _vsnprintf(buffer, size, fmt, args);
va_end(args);
return n;
}
int sscanf(const char *buffer, const char *fmt, ...) {
TRACE("sscanf");
if (strcmp(fmt, "%I64d") == 0) {
unsigned __int64 *np;
va_list args;
va_start(args, fmt);
np = va_arg(args, unsigned __int64 *);
*np = atoi(buffer);
va_end(args);
return 1;
}
syslog(LOG_DEBUG, "sscanf '%s' format '%s'", buffer, fmt);
panic("sscanf not implemented");
return 0;
}
char *_getenv(const char *option) {
TRACE("getenv");
return getenv(option);
}
int *__errno() {
TRACE("_errno");
return &(gettib()->errnum);
}
char *_strerror(int errnum)
{
return strerror(errnum);
}
unsigned long _beginthreadex(void *security, unsigned stack_size, unsigned (__stdcall *start_address)(void * ), void *arglist, unsigned initflag, unsigned *thrdaddr) {
struct tib *tib;
handle_t hthread;
TRACE("_beginthreadex");
hthread = beginthread((void (__stdcall *)(void *)) start_address, stack_size, arglist, initflag, NULL, &tib);
if (hthread >= 0 && thrdaddr && tib) *thrdaddr = tib->tid;
return hthread;
}
void _endthreadex(unsigned retval) {
TRACE("_endthreadex");
endthread(retval);
}
void abort() {
TRACE("abort");
raise(SIGABRT);
}
void __exit(int status) {
TRACE("_exit");
exit(status);
}
int crt_raise(int sig) {
TRACE("raise");
raise(sig);
return 0;
}
void (*crt_signal(int sig, void (*func)(int)))(int) {
TRACE("signal");
return signal(sig, func);
}
void _assert(void *expr, void *filename, unsigned lineno) {
TRACE("_assert");
printf("Assertion failed: %s, file %s, line %d\n", expr, filename, lineno);
abort();
}
int _getpid() {
return getpid();
}
void _ftime(struct timeb *timeptr) {
struct timeval tv;
gettimeofday(&tv, NULL);
timeptr->dstflag = 0;
timeptr->timezone = 0;
timeptr->time = tv.tv_sec;
timeptr->millitm = (unsigned short) (tv.tv_usec / 1000);
}
char *_strdup(const char *s) {
char *t;
int len;
if (!s) return NULL;
len = strlen(s);
t = (char *) malloc(len + 1);
memcpy(t, s, len + 1);
return t;
}
void srand(unsigned int seed) {
holdrand = (long) seed;
}
int rand() {
return (((holdrand = holdrand * 214013L + 2531011L) >> 16) & 0x7fff);
}
int convert_filename_to_unicode(const char *src, wchar_t *dst, int maxlen) {
wchar_t *end = dst + maxlen;
while (*src) {
if (dst == end) {
errno = ENAMETOOLONG;
return -1;
}
*dst++ = (unsigned char) *src++;
}
if (dst == end) {
errno = ENAMETOOLONG;
return -1;
}
*dst = 0;
return 0;
}
int convert_filename_from_unicode(const wchar_t *src, char *dst, int maxlen) {
char *end = dst + maxlen;
while (*src) {
if (dst == end) {
errno = ENAMETOOLONG;
return -1;
}
if (*src & 0xFF00) {
errno = EINVAL;
return -1;
}
*dst++ = (unsigned char) *src++;
}
if (dst == end) {
errno = ENAMETOOLONG;
return -1;
}
*dst = 0;
return 0;
}
size_t wcslen(const wchar_t *s) {
const wchar_t *eos = s;
while (*eos++);
return (int) (eos - s - 1);
}
// The MSVC8 compiler complains about the definitions for the
// instrinsic functions wcscpy and wcscat. For now we just
// ignore the warning.
#pragma warning(disable: 4142) // warning C4142: benign redefinition of type
wchar_t *wcscpy(wchar_t *dst, const wchar_t *src) {
wchar_t *cp = dst;
while (*cp++ = *src++);
return dst;
}
wchar_t *wcscat(wchar_t *dst, const wchar_t *src) {
wchar_t *cp = dst;
while (*cp) cp++;
while (*cp++ = *src++);
return dst;
}
int wcscmp(const wchar_t *s1, const wchar_t *s2) {
int ret = 0;
while (!(ret = *(unsigned short *) s1 - *(unsigned short *) s2) && *s2) ++s1, ++s2;
if (ret < 0) {
ret = -1;
} else if (ret > 0) {
ret = 1;
}
return ret;
}
int _wcsicmp(const wchar_t *s1, const wchar_t *s2) {
wchar_t f, l;
do {
f = ((*s1 <= 'Z') && (*s1 >= 'A')) ? *s1 + 'a' - 'A' : *s1;
l = ((*s2 <= 'Z') && (*s2 >= 'A')) ? *s2 + 'a' - 'A' : *s2;
s1++;
s2++;
} while ((f) && (f == l));
return (int) (f - l);
}
wchar_t *wcschr(const wchar_t *s, wchar_t ch) {
while (*s && *s != (wchar_t) ch) s++;
if (*s == (wchar_t) ch) return (wchar_t *) s;
return NULL;
}
int towlower(wint_t c) {
if (c < 256) {
return tolower(c);
} else {
return c;
}
}
int towupper(wint_t c) {
if (c < 256) {
return toupper(c);
} else {
return c;
}
}
int iswctype(wint_t c, int mask) {
if (c < 256) {
return 0;
} else {
return _isctype(c, mask);
}
}
void init_fileio();
int __stdcall dllmain(handle_t hmod, int reason, void *reserved) {
if (reason == DLL_PROCESS_ATTACH) {
init_fileio();
}
return 1;
}