--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/genericopenlibs/openenvcore/libc/src/libc_init/ucrt0.cpp Tue Feb 02 02:01:42 2010 +0200
@@ -0,0 +1,481 @@
+// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Common code useful to all crt0 variants. This is kept in the DLL to allow us to
+// change it in future releases.
+//
+//
+
+#include <e32std.h>
+#include <e32base.h>
+#include <unistd.h> // for chdir, environ
+#include <stdlib.h> // for calloc
+#include <string.h> // for strdup
+#include <wchar.h> // for wcsdup
+#include <fcntl.h> // for O_RDONLY, O_WRONLY and O_CREAT
+#include "estlib.h"
+#include "sysif.h"
+#include "libc_private.h"
+
+
+extern "C" {
+void SetupEnviron();
+void GetTmpDirName();
+}
+
+const TInt KMaxArgC=20;
+
+static char* wcstombs_alloc (const wchar_t* aString)
+ {
+ if (aString==NULL)
+ return NULL;
+
+ size_t size = wcstombs(0, aString, 0);
+ char* buf = (char*)User::Alloc((size+1) * sizeof(char));
+ size = wcstombs(buf, aString, size);
+
+ if (size == (size_t)-1)
+ {
+ User::Free(buf);
+ return NULL;
+ }
+ buf[size] = '\0';
+ return buf;
+ }
+
+#ifdef EKA2
+
+static wchar_t* allocCommandLine(const TDesC& aPath)
+ {
+ TInt cmdLength = User::CommandLineLength()+1; // for zero termination
+ TText16* cmdbuf = (TText16*)User::Alloc(cmdLength*sizeof(TText16));
+ if (cmdbuf==0)
+ return (wchar_t*)cmdbuf; // we are just doomed, so give up now
+
+ TPtr16 cmdline(cmdbuf, cmdLength);
+ User::CommandLine(cmdline);
+
+ // The .EXE recogniser supplies a command line which is the name of the file,
+ // followed by a space. This is usually not what's wanted, so remove the
+ // filename if it is an exact match for the start of the command line.
+
+ if (cmdline.Find(aPath)==0)
+ {
+ cmdline.Delete(0, aPath.Length());
+ }
+ cmdline.ZeroTerminate();
+ return (wchar_t*)cmdbuf;
+ }
+
+#else//EKA2
+
+static wchar_t* allocCommandLine(const TDesC& aPath)
+ {
+ RProcess me;
+ TInt cmdLength = me.CommandLineLength()+1; // for zero termination
+ TText16* cmdbuf = (TText16*)User::Alloc(cmdLength*sizeof(TText16));
+ if (cmdbuf==0)
+ return (wchar_t*)cmdbuf; // we are just doomed, so give up now
+
+ TPtr16 cmdline(cmdbuf, cmdLength);
+ me.CommandLine(cmdline);
+
+ // The .EXE recogniser supplies a command line which is the name of the file,
+ // followed by a space. This is usually not what's wanted, so remove the
+ // filename if it is an exact match for the start of the command line.
+
+ if (cmdline.Find(aPath)==0)
+ {
+ cmdline.Delete(0, aPath.Length());
+ }
+ cmdline.ZeroTerminate();
+ return (wchar_t*)cmdbuf;
+ }
+
+#endif//EKA2
+
+EXPORT_C void __crt0(int& argc, char**& argv, char**& envp)
+ {
+ wchar_t** wenvp = 0;
+ int envcnt = 0;
+
+ // Check to see if I was the product of a popen/popen3/posix_spawn/system op.
+ Backend()->CheckOrigins(wenvp, envcnt);
+
+ if (wenvp)
+ {
+ // Parent has passed in the an environ for the child. Update envp
+ envp = (char **)User::Alloc((envcnt+1) * sizeof(char*));
+ if (envp)
+ {
+ for (int i = 0; i < envcnt; ++i)
+ {
+ int len = wcslen(wenvp[i]) + 1;
+ envp[i] = (char *)User::Alloc(len * sizeof(char));
+ if (!envp[i] || (wcstombs(envp[i], wenvp[i], len) == (size_t)-1))
+ {
+ // if envp[i] is NULL, Free does nothing
+ User::Free(envp[i]);
+ envp[i] = 0;
+ break;
+ }
+ }
+ // set the terminal zero
+ envp[envcnt] = 0;
+ }
+
+ // Cleanup wenvp allocated in CheckOrigins
+ for (int i = 0; i < envcnt; ++i)
+ {
+ User::Free(wenvp[i]);
+ }
+ User::Free(wenvp);
+ }
+ else
+ {
+ // set envp from environ
+ char** temp = environ;
+ for (envcnt = 0; temp[envcnt]; ++envcnt) { }
+ // account for the terminal zero in alloc
+ envp = (char**)User::Alloc((envcnt+1) * sizeof(char*));
+ if (envp)
+ {
+ for(int i = 0; i < envcnt; ++i)
+ {
+ int len = strlen(temp[i]) + 1;
+ envp[i] = (char*)User::Alloc(len * sizeof(char));
+ if (!envp[i])
+ {
+ envp[i] = NULL;
+ break;
+ }
+ strncpy(envp[i], temp[i], len);
+ }
+ // set the terminal zero
+ envp[envcnt] = NULL;
+ }
+ }
+
+ // Find out the filename for argv[0]
+ TBuf16<KMaxFileName+1> exepath(RProcess().FileName());
+
+ // Sort out argc/argv, creating an array of pointers into a copy of
+ // the commandline.
+
+ wchar_t* cmdbuf = allocCommandLine(exepath);
+ char* cmd = wcstombs_alloc(cmdbuf);
+ User::Free(cmdbuf);
+ char* filename = wcstombs_alloc((const wchar_t *)exepath.PtrZ());
+
+ //Copy program name now so that it can be accessed by others
+ __progname = filename;
+
+ argv = (char**)calloc(KMaxArgC, sizeof(char*));
+ if (argv==0 || cmd==0 || filename== 0)
+ return; // it's basically doomed at this point anyway
+
+ //Check if there are redirection operators in the arguments
+ char* ptr = strpbrk(cmd, "<>");
+ if (ptr)
+ {
+ char* p1 = ptr, *p2;
+ int opfd, ipfd;
+
+ switch (*p1)
+ {
+ case '<':
+ p2 = strchr(++p1, '>');
+ if (p2)
+ {
+ *p2++ = 0;
+ if (*p2 == '>')
+ {
+ opfd = open(++p2, O_WRONLY|O_CREAT|O_APPEND);
+ }
+ else
+ {
+ opfd = open(p2, O_WRONLY|O_CREAT|O_TRUNC);
+ }
+
+ if (opfd > 0)
+ {
+ dup2(opfd, 1);
+ }
+ }
+
+ ipfd = open(p1, O_RDONLY);
+ if (ipfd > 0)
+ {
+ dup2(ipfd, 0);
+ }
+ break;
+ case '>':
+ p2 = strchr(++p1, '<');
+ if (p2)
+ {
+ *p2++ = 0;
+ ipfd = open(p2, O_RDONLY);
+ if (ipfd > 0)
+ {
+ dup2(ipfd, 0);
+ }
+ }
+
+ if (*p1 == '>')
+ {
+ opfd = open(++p1, O_WRONLY|O_CREAT|O_APPEND);
+ }
+ else
+ {
+ opfd = open(p1, O_WRONLY|O_CREAT|O_TRUNC);
+ }
+
+ if (opfd > 0)
+ {
+ dup2(opfd, 1);
+ }
+ break;
+ default:
+ break;
+ }
+
+ // Ensure that only the string until the first redirection operator
+ // is considered for command args processing
+ *ptr = 0;
+ }
+
+ // Split the command line into the separate arguments
+ // Follow the stdarg.c rules in the Win32 runtime, namely
+ // 1. space and tab are whitespace separators, except inside "..." pairs
+ // 2. strings of \ are literal unless followed by " (see below)
+ // 3. a pair of "" in a quoted string is a literal "
+
+ const char KSpace= ' ';
+ const char KTab = '\t';
+ const char KQuote= '"';
+ const char KSlash= '\\';
+
+ argv[0]=filename;
+ argc = 1;
+ char *q = cmd;
+ const char* p = cmd;
+ int currentMaxArgc = KMaxArgC;
+ FOREVER
+ {
+ char c;
+ TInt quoted=0;
+
+ // skip leading whitespace
+ do
+ c=*p++;
+ while (c && (c==KSpace || c==KTab));
+
+ // update the argv,argc
+ if (c=='\0')
+ break;
+ else if(argc >= currentMaxArgc)
+ {
+ currentMaxArgc += KMaxArgC;
+ argv = (char**)realloc(argv, currentMaxArgc * sizeof(char*));
+ }
+
+ argv[argc] = q;
+ argc++;
+
+ // copy the argument from p to q
+ for (;c!='\0';c=*p++)
+ {
+
+ // Poor buggers have to cope with UNC filenames, e.g. \\host\dir\file
+ // Hence the rather odd rules: for N>=0
+ // 2N+1 slash + " => N slash + literal "
+ // 2N slash + " => N slash, start/end quoted substring
+ // N slash + ? => N slash + ?
+
+ int slashcount=0;
+ while (c==KSlash)
+ {
+ *q++=c; // copy the slashes (might be too many)
+ slashcount++;
+ c=*p++;
+ }
+ if (c=='\0')
+ break;
+ if (c==KQuote)
+ {
+ q-=(slashcount-(slashcount/2)); // slashes followed by quote - adjust
+ if (slashcount&1)
+ {
+ *q++=c; // literal quote
+ continue;
+ }
+ if (quoted && *p==KQuote)
+ {
+ p++;
+ *q++=c; // "" inside quoted section = literal quote
+ continue;
+ }
+ quoted=!quoted;
+ continue;
+ }
+ if (!quoted && (c==KSpace || c==KTab))
+ break;
+ *q++=c;
+ }
+ *q++='\0'; // terminate the copy
+
+ if (c=='\0')
+ break; // end of command line
+ }
+
+ //If environ is not yet initialized for this Process
+ SetupEnviron();
+ }
+
+EXPORT_C void __crt0(int& argc, wchar_t**& wargv, wchar_t**& wenvp)
+ {
+ int envcnt = 0;
+
+ // Check to see if I was the product of a popen/popen3/posix_spawn/system op.
+ Backend()->CheckOrigins(wenvp, envcnt);
+
+ if (!wenvp)
+ {
+ // set wenvp from environ
+ char** temp = environ;
+ for (envcnt = 0; temp[envcnt]; ++envcnt) { }
+ // account for the terminal zero during alloc
+ wenvp = (wchar_t**)User::Alloc((envcnt+1) * sizeof(wchar_t*));
+ if (wenvp)
+ {
+ for(int i = 0; i < envcnt; ++i)
+ {
+ int len = strlen(temp[i])+1;
+ wenvp[i] = (wchar_t*)User::Alloc(len * sizeof(wchar_t));
+ if (!wenvp[i] || (mbstowcs(wenvp[i], temp[i], len) == (size_t)-1))
+ {
+ // if wenvp[i] is NULL, Free does nothing
+ User::Free(wenvp[i]);
+ wenvp[i] = NULL;
+ break;
+ }
+ }
+ // set the terminal 0
+ wenvp[envcnt] = NULL;
+ }
+ }
+
+ // Find out the filename for argv[0]
+ TBuf16<KMaxFileName+1> exepath(RProcess().FileName());
+
+ // Sort out argc/argv, creating an array of pointers into a copy of
+ // the commandline.
+
+ wchar_t* cmd = allocCommandLine(exepath);
+ //coverity[alloc_fn]
+ //coverity[assign]
+ wchar_t* filename = wcsdup((const wchar_t *)exepath.PtrZ());
+ wargv = (wchar_t**)calloc(KMaxArgC, sizeof(wchar_t*));
+
+ if (wargv==0 || cmd==0 || filename==0)
+ //coverity[memory_leak]
+ return; // it's basically doomed at this point anyway
+
+ // Split the command line into the separate arguments
+ // Follow the stdarg.c rules in the Win32 runtime, namely
+ // 1. space and tab are whitespace separators, except inside "..." pairs
+ // 2. strings of \ are literal unless followed by " (see below)
+ // 3. a pair of "" in a quoted string is a literal "
+
+ const wchar_t KSpace= L' ';
+ const wchar_t KTab = L'\t';
+ const wchar_t KQuote= L'"';
+ const wchar_t KSlash= L'\\';
+
+ wargv[0]=filename;
+ argc = 1;
+ wchar_t *q = cmd;
+ wchar_t *p = cmd;
+ int currentMaxArgc = KMaxArgC;
+ FOREVER
+ {
+ wchar_t c;
+ TInt quoted=0;
+
+ // skip leading whitespace
+ do
+ c=*p++;
+ while (c && (c==KSpace || c==KTab));
+
+ // update the argv,argc
+ if (c=='\0')
+ break;
+ else if(argc >= currentMaxArgc)
+ {
+ currentMaxArgc += KMaxArgC;
+ wargv = (wchar_t**)realloc(wargv, currentMaxArgc * sizeof(wchar_t*));
+ }
+
+ wargv[argc] = q;
+ argc++;
+
+ // copy the argument from p to q
+ for (;c!=L'\0';c=*p++)
+ {
+
+ // Poor buggers have to cope with UNC filenames, e.g. \\host\dir\file
+ // Hence the rather odd rules: for N>=0
+ // 2N+1 slash + " => N slash + literal "
+ // 2N slash + " => N slash, start/end quoted substring
+ // N slash + ? => N slash + ?
+
+ int slashcount=0;
+ while (c==KSlash)
+ {
+ *q++=c; // copy the slashes (might be too many)
+ slashcount++;
+ c=*p++;
+ }
+ if (c==L'\0')
+ break;
+ if (c==KQuote)
+ {
+ q-=(slashcount-(slashcount/2)); // slashes followed by quote - adjust
+ if (slashcount&1)
+ {
+ *q++=c; // literal quote
+ continue;
+ }
+ if (quoted && *p==KQuote)
+ {
+ p++;
+ *q++=c; // "" inside quoted section = literal quote
+ continue;
+ }
+ quoted=!quoted;
+ continue;
+ }
+ if (!quoted && (c==KSpace || c==KTab))
+ break;
+ *q++=c;
+ }
+ *q++=L'\0'; // terminate the copy
+
+ if (c==L'\0')
+ break; // end of command line
+ }
+
+ //If environ is not yet initialized for this Process
+ SetupEnviron();
+ GetTmpDirName();
+ }