2001-12-17 14:31:42 +00:00
|
|
|
/** Implementation for NSProcessInfo for GNUStep
|
2017-07-07 08:50:10 +00:00
|
|
|
Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
1995-08-16 15:47:12 +00:00
|
|
|
|
2001-12-17 14:31:42 +00:00
|
|
|
Written by: Georg Tuparev <Tuparev@EMBL-Heidelberg.de>
|
1995-08-16 15:47:12 +00:00
|
|
|
Heidelberg, Germany
|
2001-12-17 14:31:42 +00:00
|
|
|
Modified by: Richard Frith-Macdonald <rfm@gnu.org>
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1996-05-12 00:56:10 +00:00
|
|
|
This file is part of the GNUstep Base Library.
|
1995-08-16 15:47:12 +00:00
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
2007-09-14 11:36:11 +00:00
|
|
|
modify it under the terms of the GNU Lesser General Public
|
1995-08-16 15:47:12 +00:00
|
|
|
License as published by the Free Software Foundation; either
|
2008-06-08 10:38:33 +00:00
|
|
|
version 2 of the License, or (at your option) any later version.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
2019-12-09 23:36:00 +00:00
|
|
|
Lesser General Public License for more details.
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2007-09-14 11:36:11 +00:00
|
|
|
You should have received a copy of the GNU Lesser General Public
|
1995-08-16 15:47:12 +00:00
|
|
|
License along with this library; if not, write to the Free
|
2006-03-08 11:28:59 +00:00
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
2019-12-09 23:36:00 +00:00
|
|
|
Boston, MA 02110 USA.
|
2001-12-18 16:54:15 +00:00
|
|
|
|
|
|
|
<title>NSProcessInfo class reference</title>
|
|
|
|
$Date$ $Revision$
|
2005-02-22 11:22:44 +00:00
|
|
|
*/
|
1995-08-16 15:47:12 +00:00
|
|
|
|
|
|
|
/*************************************************************************
|
|
|
|
* File Name : NSProcessInfo.m
|
|
|
|
* Date : 06-aug-1995
|
|
|
|
*************************************************************************
|
2005-02-22 11:22:44 +00:00
|
|
|
* Notes :
|
1995-08-16 15:47:12 +00:00
|
|
|
* 1) The class functionality depends on the following UNIX functions and
|
|
|
|
* global variables: gethostname(), getpid(), and environ. For all system
|
|
|
|
* I had the opportunity to test them they are defined and have the same
|
|
|
|
* behavior. The same is true for the meaning of argv[0] (process name).
|
|
|
|
* 2) The global variable _gnu_sharedProcessInfoObject should NEVER be
|
2005-02-22 11:22:44 +00:00
|
|
|
* deallocate during the process runtime. Therefore I implemented a
|
1995-08-16 15:47:12 +00:00
|
|
|
* concrete NSProcessInfo subclass (_NSConcreteProcessInfo) with the only
|
|
|
|
* purpose to override the autorelease, retain, and release methods.
|
2005-02-22 11:22:44 +00:00
|
|
|
* To Do :
|
1995-08-16 15:47:12 +00:00
|
|
|
* 1) To test the class on more platforms;
|
|
|
|
* Bugs : Not known
|
2002-08-07 16:15:01 +00:00
|
|
|
* Last update: 07-aug-2002
|
1995-08-16 15:47:12 +00:00
|
|
|
* History : 06-aug-1995 - Birth and the first beta version (v. 0.5);
|
|
|
|
* 08-aug-1995 - V. 0.6 (tested on NS, SunOS, Solaris, OSF/1
|
2005-02-22 11:22:44 +00:00
|
|
|
* The use of the environ global var was changed to more
|
1995-08-16 15:47:12 +00:00
|
|
|
* conventional env[] (main function) so now the class could be
|
|
|
|
* used on SunOS and Solaris. [GT]
|
|
|
|
*************************************************************************
|
2005-02-22 11:22:44 +00:00
|
|
|
* Acknowledgments:
|
1995-08-16 15:47:12 +00:00
|
|
|
* - Adam Fedor, Andrew McCallum, and Paul Kunz for their help;
|
|
|
|
* - To the NEXTSTEP/GNUStep community
|
|
|
|
*************************************************************************/
|
|
|
|
|
2010-02-19 08:12:46 +00:00
|
|
|
#import "common.h"
|
1997-11-06 00:51:23 +00:00
|
|
|
|
1997-12-19 18:13:52 +00:00
|
|
|
#include <stdio.h>
|
2007-08-02 09:36:38 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
|
|
|
# include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
2011-12-15 09:42:39 +00:00
|
|
|
#if defined(HAVE_SYS_SIGNAL_H)
|
|
|
|
# include <sys/signal.h>
|
|
|
|
#elif defined(HAVE_SIGNAL_H)
|
|
|
|
# include <signal.h>
|
2007-08-02 09:36:38 +00:00
|
|
|
#endif
|
2011-12-15 09:42:39 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_SYS_FILE_H)
|
|
|
|
# include <sys/file.h>
|
2007-08-02 09:36:38 +00:00
|
|
|
#endif
|
|
|
|
|
2011-12-15 09:42:39 +00:00
|
|
|
#if defined(HAVE_SYS_FCNTL_H)
|
|
|
|
# include <sys/fcntl.h>
|
|
|
|
#elif defined(HAVE_FCNTL_H)
|
|
|
|
# include <fcntl.h>
|
2002-06-15 13:39:47 +00:00
|
|
|
#endif
|
2011-12-15 09:42:39 +00:00
|
|
|
|
2006-10-03 13:35:50 +00:00
|
|
|
#ifdef HAVE_SYS_UTSNAME_H
|
|
|
|
#include <sys/utsname.h>
|
|
|
|
#endif
|
2002-05-27 14:03:10 +00:00
|
|
|
|
2004-06-14 22:27:22 +00:00
|
|
|
#ifdef HAVE_KVM_ENV
|
2003-06-24 02:45:29 +00:00
|
|
|
#include <kvm.h>
|
2011-12-15 09:42:39 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_SYS_FCNTL_H)
|
|
|
|
# include <sys/fcntl.h>
|
|
|
|
#elif defined(HAVE_FCNTL_H)
|
|
|
|
# include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2003-06-24 02:45:29 +00:00
|
|
|
#include <sys/param.h>
|
2004-06-14 22:27:22 +00:00
|
|
|
#endif /* HAVE_KVM_ENV */
|
2003-06-24 02:45:29 +00:00
|
|
|
|
2008-11-13 14:28:56 +00:00
|
|
|
#ifdef HAVE_SYS_SYSCTL_H
|
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#endif
|
|
|
|
|
2005-08-12 17:34:19 +00:00
|
|
|
#if HAVE_PROCFS_H
|
|
|
|
#define id _procfs_avoid_id_collision
|
|
|
|
#include <procfs.h>
|
|
|
|
#undef id
|
|
|
|
#endif
|
|
|
|
|
2011-03-17 22:33:31 +00:00
|
|
|
#if defined(__APPLE__) && !GS_FAKE_MAIN
|
|
|
|
#include <crt_externs.h>
|
|
|
|
#endif
|
|
|
|
|
2010-02-14 10:48:10 +00:00
|
|
|
#import "Foundation/NSArray.h"
|
|
|
|
#import "Foundation/NSSet.h"
|
2011-10-22 13:59:05 +00:00
|
|
|
#import "Foundation/NSCharacterSet.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
#import "Foundation/NSDictionary.h"
|
|
|
|
#import "Foundation/NSDate.h"
|
|
|
|
#import "Foundation/NSException.h"
|
2011-10-22 13:59:05 +00:00
|
|
|
#import "Foundation/NSFileManager.h"
|
2010-02-14 10:48:10 +00:00
|
|
|
#import "Foundation/NSProcessInfo.h"
|
|
|
|
#import "Foundation/NSAutoreleasePool.h"
|
|
|
|
#import "Foundation/NSHost.h"
|
|
|
|
#import "Foundation/NSLock.h"
|
|
|
|
#import "GNUstepBase/NSProcessInfo+GNUstepBase.h"
|
|
|
|
#import "GNUstepBase/NSString+GNUstepBase.h"
|
1995-08-16 15:47:12 +00:00
|
|
|
|
2010-02-17 11:47:06 +00:00
|
|
|
#import "GSPrivate.h"
|
2002-03-27 09:55:57 +00:00
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
/* This error message should be called only if the private main function
|
1999-07-22 14:17:27 +00:00
|
|
|
* was not executed successfully. This may happen ONLY if another library
|
1999-03-02 08:58:30 +00:00
|
|
|
* or kit defines its own main function (as gnustep-base does).
|
1995-08-16 15:47:12 +00:00
|
|
|
*/
|
1999-07-22 14:17:27 +00:00
|
|
|
#if GS_FAKE_MAIN
|
2016-02-15 12:13:37 +00:00
|
|
|
#define _GNU_MISSING_MAIN_FUNCTION_CALL "\nGNUSTEP Internal Error:\n\
|
1999-07-22 14:17:27 +00:00
|
|
|
The private GNUstep function to establish the argv and environment\n\
|
|
|
|
variables was not called.\n\
|
|
|
|
Perhaps your program failed to #include <Foundation/NSObject.h> or\n\
|
|
|
|
<Foundation/Foundation.h>?\n\
|
|
|
|
If that is not the problem, Please report the error to bug-gnustep@gnu.org.\n\n"
|
|
|
|
#else
|
2000-06-30 22:42:48 +00:00
|
|
|
#ifdef GS_PASS_ARGUMENTS
|
2016-02-15 12:13:37 +00:00
|
|
|
#define _GNU_MISSING_MAIN_FUNCTION_CALL "\nGNUSTEP Error:\n\
|
2000-06-30 22:42:48 +00:00
|
|
|
A call to NSProcessInfo +initializeWithArguments:... must be made\n\
|
|
|
|
as the first ObjC statment in main. This function is used to \n\
|
|
|
|
establish the argv and environment variables.\n"
|
|
|
|
#else
|
2016-02-15 12:13:37 +00:00
|
|
|
#define _GNU_MISSING_MAIN_FUNCTION_CALL "\nGNUSTEP Internal Error:\n\
|
1999-07-22 14:17:27 +00:00
|
|
|
The private GNUstep function to establish the argv and environment\n\
|
|
|
|
variables was not called.\n\
|
2006-04-23 22:22:26 +00:00
|
|
|
\n\
|
|
|
|
Mismatched library versions between GNUstep Foundation (base) and AppKit\n\
|
|
|
|
(gui) is most often the cause of this message. Please be sure you\n\
|
|
|
|
are using known compatible versions and not a mismatched set. Generally,\n\
|
|
|
|
we recommend you use versions of base and gui which were released together.\n\
|
|
|
|
\n\
|
|
|
|
For more detailed assistance, please report the error to bug-gnustep@gnu.org.\n\n"
|
1999-07-22 14:17:27 +00:00
|
|
|
#endif
|
2000-06-30 22:42:48 +00:00
|
|
|
#endif
|
1995-08-16 15:47:12 +00:00
|
|
|
|
2014-04-19 01:34:48 +00:00
|
|
|
@interface NSHost (NSProcessInfo)
|
|
|
|
+ (NSString*) _myHostName;
|
|
|
|
@end
|
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*** _NSConcreteProcessInfo
|
|
|
|
*************************************************************************/
|
1999-07-22 14:17:27 +00:00
|
|
|
@interface _NSConcreteProcessInfo: NSProcessInfo
|
|
|
|
- (id) autorelease;
|
2021-08-10 15:02:06 +00:00
|
|
|
- (oneway void) release;
|
1999-07-22 14:17:27 +00:00
|
|
|
- (id) retain;
|
1995-08-16 15:47:12 +00:00
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation _NSConcreteProcessInfo
|
1999-07-22 14:17:27 +00:00
|
|
|
- (id) autorelease
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-08-16 16:14:11 +00:00
|
|
|
return self;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2021-08-10 15:02:06 +00:00
|
|
|
- (oneway void) release
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-08-16 16:14:11 +00:00
|
|
|
return;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
- (id) retain
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-08-16 16:14:11 +00:00
|
|
|
return self;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
2004-06-22 22:40:40 +00:00
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
/*************************************************************************
|
|
|
|
*** NSProcessInfo implementation
|
|
|
|
*************************************************************************/
|
2004-06-22 22:40:40 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Instances of this class encapsulate information on the current process.
|
|
|
|
* For example, you can get the arguments, environment variables, host name,
|
|
|
|
* or process name. There is only one instance per process, for obvious
|
|
|
|
* reasons, and it may be obtained through the +processInfo method.
|
|
|
|
*/
|
1995-08-16 15:47:12 +00:00
|
|
|
@implementation NSProcessInfo
|
|
|
|
/*************************************************************************
|
|
|
|
*** Static global vars
|
|
|
|
*************************************************************************/
|
2014-10-17 13:42:34 +00:00
|
|
|
|
|
|
|
// The lock to protect shared process resources.
|
|
|
|
static NSRecursiveLock *procLock = nil;
|
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
// The shared NSProcessInfo instance
|
1999-07-22 14:17:27 +00:00
|
|
|
static NSProcessInfo *_gnu_sharedProcessInfoObject = nil;
|
1995-08-16 15:47:12 +00:00
|
|
|
|
|
|
|
// Host name of the CPU executing the process
|
2005-02-22 11:22:44 +00:00
|
|
|
static NSString *_gnu_hostName = nil;
|
1995-08-16 15:47:12 +00:00
|
|
|
|
2002-04-16 15:14:54 +00:00
|
|
|
static char *_gnu_arg_zero = 0;
|
2002-04-16 15:09:00 +00:00
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
// Current process name
|
1999-07-22 14:17:27 +00:00
|
|
|
static NSString *_gnu_processName = nil;
|
1995-08-16 15:47:12 +00:00
|
|
|
|
|
|
|
// Array of NSStrings (argv[1] .. argv[argc-1])
|
1999-07-22 14:17:27 +00:00
|
|
|
static NSArray *_gnu_arguments = nil;
|
1995-08-16 15:47:12 +00:00
|
|
|
|
|
|
|
// Dictionary of environment vars and their values
|
2011-07-24 13:09:22 +00:00
|
|
|
static NSDictionary *_gnu_environment = nil;
|
1995-08-16 15:47:12 +00:00
|
|
|
|
2006-10-03 13:35:50 +00:00
|
|
|
// The operating system we are using.
|
|
|
|
static unsigned int _operatingSystem = 0;
|
|
|
|
static NSString *_operatingSystemName = nil;
|
|
|
|
static NSString *_operatingSystemVersion = nil;
|
|
|
|
|
2006-01-04 20:53:21 +00:00
|
|
|
// Flag to indicate that fallbackInitialisation was executed.
|
|
|
|
static BOOL fallbackInitialisation = NO;
|
2006-10-03 13:35:50 +00:00
|
|
|
|
2010-02-14 10:48:10 +00:00
|
|
|
static NSMutableSet *mySet = nil;
|
2019-09-25 10:11:50 +00:00
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
static jobject _androidContext = NULL;
|
|
|
|
static NSString *_androidFilesDir = nil;
|
2019-11-05 12:37:59 +00:00
|
|
|
static NSString *_androidCacheDir = nil;
|
2024-08-20 17:19:59 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* The following macro assumes that the function's return type is bool.
|
|
|
|
*/
|
|
|
|
#define GS_JNI_CHECK(env, obj) \
|
|
|
|
if (unlikely(JNI_TRUE == (*env)->ExceptionCheck(env))) { \
|
|
|
|
fprintf(stderr, "File: %s, Line: %d jenv: %p obj: %p Pending exception in JNI environment.\n", __FILE__, __LINE__, env, obj); \
|
|
|
|
(*env)->ExceptionDescribe(env); \
|
|
|
|
(*env)->ExceptionClear(env); \
|
|
|
|
abort(); \
|
|
|
|
} \
|
|
|
|
if (unlikely(obj == NULL)) { \
|
|
|
|
fprintf(stderr, "File: %s, Line: %d jenv: %p JNI returned NULL instead of a valid JNI object.\n", __FILE__, __LINE__, env); \
|
|
|
|
abort(); \
|
|
|
|
}
|
|
|
|
#define GS_JNI_CLS_CHECK(env, cls, name) \
|
|
|
|
if (unlikely(cls == NULL)) { \
|
|
|
|
fprintf(stderr, "File: %s, Line: %d jenv: %p JNI returned NULL instead of a valid JNI class object for '%s'.\n", __FILE__, __LINE__, env, name); \
|
|
|
|
abort(); \
|
|
|
|
}
|
|
|
|
#define GS_JNI_METH_CHECK(env, meth) \
|
|
|
|
if (unlikely(meth == NULL)) { \
|
|
|
|
fprintf(stderr, "File: %s, Line: %d jenv: %p JNI returned NULL instead of a valid JNI method object.\n", __FILE__, __LINE__, env); \
|
|
|
|
abort(); \
|
|
|
|
}
|
2019-09-25 10:11:50 +00:00
|
|
|
#endif
|
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
/*************************************************************************
|
1999-07-22 14:17:27 +00:00
|
|
|
*** Implementing the gnustep_base_user_main function
|
1995-08-16 15:47:12 +00:00
|
|
|
*************************************************************************/
|
|
|
|
|
2006-10-23 14:47:37 +00:00
|
|
|
static void
|
1996-01-08 17:05:45 +00:00
|
|
|
_gnu_process_args(int argc, char *argv[], char *env[])
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
2011-02-28 19:49:57 +00:00
|
|
|
NSAutoreleasePool *arp = [NSAutoreleasePool new];
|
2005-06-04 07:22:51 +00:00
|
|
|
NSString *arg0 = nil;
|
1995-08-16 16:14:11 +00:00
|
|
|
int i;
|
1995-11-07 02:22:22 +00:00
|
|
|
|
2002-10-12 16:12:25 +00:00
|
|
|
if (_gnu_arg_zero != 0)
|
|
|
|
{
|
2011-02-19 19:42:42 +00:00
|
|
|
free(_gnu_arg_zero);
|
2002-10-12 16:12:25 +00:00
|
|
|
}
|
2003-03-23 07:06:27 +00:00
|
|
|
|
2003-08-01 10:15:11 +00:00
|
|
|
if (argv != 0 && argv[0] != 0)
|
2003-03-23 07:06:27 +00:00
|
|
|
{
|
2011-03-07 11:34:17 +00:00
|
|
|
int len;
|
|
|
|
|
|
|
|
len = strlen(argv[0]) + 1;
|
|
|
|
_gnu_arg_zero = (char*)malloc(len);
|
|
|
|
memcpy(_gnu_arg_zero, argv[0], len);
|
2005-06-04 07:22:51 +00:00
|
|
|
arg0 = [[NSString alloc] initWithCString: _gnu_arg_zero];
|
2003-03-23 07:06:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2005-06-04 07:22:51 +00:00
|
|
|
unichar *buffer;
|
2003-03-23 07:06:27 +00:00
|
|
|
int buffer_size = 0;
|
|
|
|
int needed_size = 0;
|
2011-03-07 11:34:17 +00:00
|
|
|
int len;
|
2005-06-04 07:22:51 +00:00
|
|
|
const char *tmp;
|
2003-03-23 07:06:27 +00:00
|
|
|
|
|
|
|
while (needed_size == buffer_size)
|
|
|
|
{
|
|
|
|
buffer_size = buffer_size + 256;
|
2011-02-19 19:42:42 +00:00
|
|
|
buffer = (unichar*)malloc(buffer_size * sizeof(unichar));
|
2005-06-04 07:22:51 +00:00
|
|
|
needed_size = GetModuleFileNameW(NULL, buffer, buffer_size);
|
2003-03-23 07:06:27 +00:00
|
|
|
if (needed_size < buffer_size)
|
|
|
|
{
|
2005-06-04 07:22:51 +00:00
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
for (i = 0; i < needed_size; i++)
|
|
|
|
{
|
|
|
|
if (buffer[i] == 0)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
arg0 = [[NSString alloc] initWithCharacters: buffer length: i];
|
2003-03-23 07:06:27 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-02-19 19:42:42 +00:00
|
|
|
free(buffer);
|
2003-03-23 07:06:27 +00:00
|
|
|
}
|
|
|
|
}
|
2006-10-09 14:00:01 +00:00
|
|
|
tmp = [arg0 cStringUsingEncoding: [NSString defaultCStringEncoding]];
|
2011-03-07 11:34:17 +00:00
|
|
|
len = strlen(tmp) + 1;
|
|
|
|
_gnu_arg_zero = (char*)malloc(len);
|
|
|
|
memcpy(_gnu_arg_zero, tmp, len);
|
2005-02-22 11:22:44 +00:00
|
|
|
#else
|
|
|
|
fprintf(stderr, "Error: for some reason, argv not properly set up "
|
2003-03-23 07:06:27 +00:00
|
|
|
"during GNUstep base initialization\n");
|
|
|
|
abort();
|
2005-02-22 11:22:44 +00:00
|
|
|
#endif
|
2003-03-23 07:06:27 +00:00
|
|
|
}
|
2002-04-16 15:09:00 +00:00
|
|
|
|
1995-08-16 16:14:11 +00:00
|
|
|
/* Getting the process name */
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RELEASE(_gnu_processName);)
|
2005-06-04 07:22:51 +00:00
|
|
|
_gnu_processName = [arg0 lastPathComponent];
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2007-03-09 08:48:09 +00:00
|
|
|
/* On windows we remove any .exe extension for consistency with app names
|
|
|
|
* under unix
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
NSString *e = [_gnu_processName pathExtension];
|
|
|
|
|
|
|
|
if (e != nil && [e caseInsensitiveCompare: @"EXE"] == NSOrderedSame)
|
|
|
|
{
|
|
|
|
_gnu_processName = [_gnu_processName stringByDeletingPathExtension];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RETAIN(_gnu_processName);)
|
1999-07-22 14:17:27 +00:00
|
|
|
|
1995-08-16 16:14:11 +00:00
|
|
|
/* Copy the argument list */
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2006-04-26 15:33:47 +00:00
|
|
|
{
|
|
|
|
unichar **argvw = CommandLineToArgvW(GetCommandLineW(), &argc);
|
|
|
|
NSString *str;
|
|
|
|
id obj_argv[argc];
|
|
|
|
int added = 1;
|
|
|
|
|
|
|
|
/* Copy the zero'th argument to the argument list */
|
|
|
|
obj_argv[0] = arg0;
|
|
|
|
|
2010-02-14 10:48:10 +00:00
|
|
|
if (mySet == nil) mySet = [NSMutableSet new];
|
|
|
|
|
2006-04-26 15:33:47 +00:00
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
{
|
|
|
|
str = [NSString stringWithCharacters: argvw[i] length: wcslen(argvw[i])];
|
|
|
|
if ([str hasPrefix: @"--GNU-Debug="])
|
|
|
|
{
|
|
|
|
[mySet addObject: [str substringFromIndex: 12]];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
obj_argv[added++] = str;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RELEASE(_gnu_arguments);)
|
2006-04-26 15:33:47 +00:00
|
|
|
_gnu_arguments = [[NSArray alloc] initWithObjects: obj_argv count: added];
|
|
|
|
RELEASE(arg0);
|
|
|
|
}
|
|
|
|
#else
|
2006-04-12 21:45:52 +00:00
|
|
|
if (argv)
|
2006-04-26 15:33:47 +00:00
|
|
|
{
|
|
|
|
NSString *str;
|
|
|
|
id obj_argv[argc];
|
|
|
|
int added = 1;
|
2006-10-20 10:56:27 +00:00
|
|
|
NSStringEncoding enc = GSPrivateDefaultCStringEncoding();
|
1998-08-04 10:45:43 +00:00
|
|
|
|
2006-04-26 15:33:47 +00:00
|
|
|
/* Copy the zero'th argument to the argument list */
|
|
|
|
obj_argv[0] = arg0;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
2010-02-14 10:48:10 +00:00
|
|
|
if (mySet == nil) mySet = [NSMutableSet new];
|
|
|
|
|
2006-04-26 15:33:47 +00:00
|
|
|
for (i = 1; i < argc; i++)
|
|
|
|
{
|
2006-10-09 14:00:01 +00:00
|
|
|
str = [NSString stringWithCString: argv[i] encoding: enc];
|
1999-07-22 14:17:27 +00:00
|
|
|
|
2006-04-26 15:33:47 +00:00
|
|
|
if ([str hasPrefix: @"--GNU-Debug="])
|
|
|
|
[mySet addObject: [str substringFromIndex: 12]];
|
|
|
|
else
|
|
|
|
obj_argv[added++] = str;
|
|
|
|
}
|
|
|
|
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RELEASE(_gnu_arguments);)
|
2006-04-26 15:33:47 +00:00
|
|
|
_gnu_arguments = [[NSArray alloc] initWithObjects: obj_argv count: added];
|
|
|
|
RELEASE(arg0);
|
|
|
|
}
|
2006-04-12 21:45:52 +00:00
|
|
|
#endif
|
|
|
|
|
1995-08-16 16:14:11 +00:00
|
|
|
/* Copy the evironment list */
|
1995-11-03 16:12:07 +00:00
|
|
|
{
|
1999-07-22 14:17:27 +00:00
|
|
|
NSMutableArray *keys = [NSMutableArray new];
|
|
|
|
NSMutableArray *values = [NSMutableArray new];
|
2006-10-20 10:56:27 +00:00
|
|
|
NSStringEncoding enc = GSPrivateDefaultCStringEncoding();
|
1999-07-22 14:17:27 +00:00
|
|
|
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2005-12-05 08:37:16 +00:00
|
|
|
if (fallbackInitialisation == NO)
|
2005-11-05 16:20:19 +00:00
|
|
|
{
|
2005-12-05 08:37:16 +00:00
|
|
|
unichar *base;
|
1999-07-22 14:17:27 +00:00
|
|
|
|
2005-12-05 08:37:16 +00:00
|
|
|
base = GetEnvironmentStringsW();
|
|
|
|
if (base != 0)
|
1999-05-06 05:49:55 +00:00
|
|
|
{
|
2005-12-05 08:37:16 +00:00
|
|
|
const unichar *wenvp = base;
|
2005-11-05 16:20:19 +00:00
|
|
|
|
|
|
|
while (*wenvp != 0)
|
|
|
|
{
|
2005-12-05 08:37:16 +00:00
|
|
|
const unichar *start = wenvp;
|
|
|
|
NSString *key;
|
|
|
|
NSString *val;
|
|
|
|
|
|
|
|
start = wenvp;
|
|
|
|
while (*wenvp != '=' && *wenvp != 0)
|
|
|
|
{
|
|
|
|
wenvp++;
|
|
|
|
}
|
|
|
|
if (*wenvp == '=')
|
|
|
|
{
|
|
|
|
key = [NSString stringWithCharacters: start
|
|
|
|
length: wenvp - start];
|
|
|
|
wenvp++;
|
|
|
|
start = wenvp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
break; // Bad format ... expected '='
|
|
|
|
}
|
|
|
|
while (*wenvp != 0)
|
|
|
|
{
|
|
|
|
wenvp++;
|
|
|
|
}
|
|
|
|
val = [NSString stringWithCharacters: start
|
|
|
|
length: wenvp - start];
|
|
|
|
wenvp++; // Skip past variable terminator
|
|
|
|
[keys addObject: key];
|
|
|
|
[values addObject: val];
|
2005-11-05 16:20:19 +00:00
|
|
|
}
|
2005-12-05 08:37:16 +00:00
|
|
|
FreeEnvironmentStringsW(base);
|
|
|
|
env = 0; // Suppress standard code.
|
2005-02-22 11:22:44 +00:00
|
|
|
}
|
2005-11-05 16:20:19 +00:00
|
|
|
}
|
1999-05-06 05:49:55 +00:00
|
|
|
#endif
|
2005-11-05 16:20:19 +00:00
|
|
|
if (env != 0)
|
|
|
|
{
|
|
|
|
i = 0;
|
|
|
|
while (env[i])
|
|
|
|
{
|
|
|
|
int len = strlen(env[i]);
|
|
|
|
char *cp = strchr(env[i], '=');
|
|
|
|
|
|
|
|
if (len && cp)
|
|
|
|
{
|
|
|
|
char buf[len+2];
|
|
|
|
|
2011-03-07 11:34:17 +00:00
|
|
|
memcpy(buf, env[i], len + 1);
|
2005-11-05 16:20:19 +00:00
|
|
|
cp = &buf[cp - env[i]];
|
|
|
|
*cp++ = '\0';
|
2006-10-09 14:00:01 +00:00
|
|
|
[keys addObject:
|
|
|
|
[NSString stringWithCString: buf encoding: enc]];
|
|
|
|
[values addObject:
|
|
|
|
[NSString stringWithCString: cp encoding: enc]];
|
2005-11-05 16:20:19 +00:00
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
1995-11-03 16:12:07 +00:00
|
|
|
}
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RELEASE(_gnu_environment);)
|
1999-07-22 14:17:27 +00:00
|
|
|
_gnu_environment = [[NSDictionary alloc] initWithObjects: values
|
|
|
|
forKeys: keys];
|
2022-02-17 10:21:36 +00:00
|
|
|
IF_NO_ARC(RELEASE(keys);)
|
|
|
|
IF_NO_ARC(RELEASE(values);)
|
1995-08-16 16:14:11 +00:00
|
|
|
}
|
2011-05-27 11:48:44 +00:00
|
|
|
[arp drain];
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2011-03-17 22:33:31 +00:00
|
|
|
#if !GS_FAKE_MAIN && ((defined(HAVE_PROCFS) || defined(HAVE_KVM_ENV) || defined(HAVE_PROCFS_PSINFO) || defined(__APPLE__)) && (defined(HAVE_LOAD_METHOD)))
|
1999-07-22 14:17:27 +00:00
|
|
|
/*
|
|
|
|
* We have to save program arguments and environment before main () is
|
|
|
|
* executed, because main () could modify their values before we get a
|
2005-02-22 11:22:44 +00:00
|
|
|
* chance to read them
|
1995-08-28 13:36:24 +00:00
|
|
|
*/
|
2003-06-24 02:45:29 +00:00
|
|
|
static int _gnu_noobjc_argc = 0;
|
|
|
|
static char **_gnu_noobjc_argv = NULL;
|
|
|
|
static char **_gnu_noobjc_env = NULL;
|
1995-08-28 13:36:24 +00:00
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
/*
|
|
|
|
* The +load method (an extension of the GNU compiler) is invoked
|
|
|
|
* before main and +initialize (for this class) is executed. This is
|
2003-06-24 02:45:29 +00:00
|
|
|
* guaranteed if +load contains only pure C code, as we have here. The
|
|
|
|
* code in here either uses libkvm if available, or else procfs.
|
1999-07-22 14:17:27 +00:00
|
|
|
*/
|
2005-02-22 11:22:44 +00:00
|
|
|
+ (void) load
|
1997-12-19 18:13:52 +00:00
|
|
|
{
|
2004-06-14 22:27:22 +00:00
|
|
|
#ifdef HAVE_KVM_ENV
|
2003-06-24 02:45:29 +00:00
|
|
|
/*
|
|
|
|
* Use the kvm library to open the kernel and read the environment and
|
|
|
|
* arguments. As we are not running as root we cannot open the memory
|
|
|
|
* device and thus we fake it using /dev/null. This is allowed under
|
|
|
|
* FreeBSD, but may fail on other operating systems which check the
|
|
|
|
* file type. The kvm calls used are those which are supposedly backward
|
|
|
|
* compatible with Solaris rather than being FreeBSD specific
|
|
|
|
*/
|
|
|
|
kvm_t *kptr = NULL;
|
|
|
|
struct kinfo_proc *proc_ptr = NULL;
|
|
|
|
int nprocs, i, count;
|
|
|
|
char **vectors;
|
|
|
|
|
|
|
|
/* open the kernel */
|
|
|
|
kptr = kvm_open(NULL, "/dev/null", NULL, O_RDONLY, "NSProcessInfo");
|
2004-01-11 04:49:10 +00:00
|
|
|
if (!kptr)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: Your system appears to provide libkvm, but the kernel open fails\n");
|
|
|
|
fprintf(stderr, "Try to reconfigure gnustep-base with --enable-fake-main. to work\n");
|
|
|
|
fprintf(stderr, "around this problem.");
|
|
|
|
abort();
|
|
|
|
}
|
2003-06-24 02:45:29 +00:00
|
|
|
|
|
|
|
/* find the process */
|
|
|
|
proc_ptr = kvm_getprocs(kptr, KERN_PROC_PID, getpid(), &nprocs);
|
2004-01-11 04:49:10 +00:00
|
|
|
if (!proc_ptr || (nprocs != 1))
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: libkvm cannot find the current process\n");
|
|
|
|
abort();
|
|
|
|
}
|
2003-06-24 02:45:29 +00:00
|
|
|
|
2004-08-26 15:04:26 +00:00
|
|
|
/* get the environment vectors the normal way, since this always works.
|
|
|
|
On FreeBSD, the only other way is via /proc, and in later versions
|
|
|
|
/proc is not mounted. */
|
|
|
|
{
|
|
|
|
extern char **environ;
|
|
|
|
vectors = environ;
|
|
|
|
if (!vectors)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: for some reason, environ == NULL "
|
|
|
|
"during GNUstep base initialization\n"
|
|
|
|
"Please check the linking process\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
2003-06-24 02:45:29 +00:00
|
|
|
|
|
|
|
/* copy the environment strings */
|
2005-02-22 11:22:44 +00:00
|
|
|
for (count = 0; vectors[count]; count++)
|
2003-06-24 02:45:29 +00:00
|
|
|
;
|
2011-02-19 19:42:42 +00:00
|
|
|
_gnu_noobjc_env = (char**)malloc(sizeof(char*) * (count + 1));
|
2003-06-24 02:45:29 +00:00
|
|
|
if (!_gnu_noobjc_env)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < count; i++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_env[i] = (char *)strdup(vectors[i]);
|
|
|
|
if (!_gnu_noobjc_env[i])
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_env[i] = NULL;
|
|
|
|
|
|
|
|
/* get the argument vectors */
|
|
|
|
vectors = kvm_getargv(kptr, proc_ptr, 0);
|
2004-01-11 04:49:10 +00:00
|
|
|
if (!vectors)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: libkvm does not return arguments for the current process\n");
|
2008-11-18 09:41:38 +00:00
|
|
|
fprintf(stderr, "this may be due to a bug (undocumented feature) in libkvm\n");
|
|
|
|
fprintf(stderr, "which fails to get arguments unless /proc is mounted.\n");
|
|
|
|
fprintf(stderr, "If so, you can mount the /proc filesystem or reconfigure/build\n");
|
|
|
|
fprintf(stderr, "gnustep-base with --enable-fake-main as a workaround, and\n");
|
|
|
|
fprintf(stderr, "should report the bug to the maintainer of libkvm on your operating system.\n");
|
2004-01-11 04:49:10 +00:00
|
|
|
abort();
|
|
|
|
}
|
2003-06-24 02:45:29 +00:00
|
|
|
|
|
|
|
/* copy the argument strings */
|
2005-02-22 11:22:44 +00:00
|
|
|
for (_gnu_noobjc_argc = 0; vectors[_gnu_noobjc_argc]; _gnu_noobjc_argc++)
|
2003-06-24 02:45:29 +00:00
|
|
|
;
|
2006-05-24 08:27:39 +00:00
|
|
|
_gnu_noobjc_argv
|
2011-02-19 19:42:42 +00:00
|
|
|
= (char**)malloc(sizeof(char*) * (_gnu_noobjc_argc + 1));
|
2003-06-24 02:45:29 +00:00
|
|
|
if (!_gnu_noobjc_argv)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < _gnu_noobjc_argc; i++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_argv[i] = (char *)strdup(vectors[i]);
|
|
|
|
if (!_gnu_noobjc_argv[i])
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_argv[i] = NULL;
|
|
|
|
|
2005-08-12 17:34:19 +00:00
|
|
|
return;
|
|
|
|
#elif defined(HAVE_PROCFS_PSINFO)
|
|
|
|
char *proc_file_name = NULL;
|
|
|
|
FILE *ifp;
|
|
|
|
psinfo_t pinfo;
|
|
|
|
char **vectors;
|
|
|
|
int i, count;
|
|
|
|
|
|
|
|
// Read commandline
|
2011-03-07 15:34:06 +00:00
|
|
|
proc_file_name = (char*)malloc(2048);
|
|
|
|
snprintf(proc_file_name, 2048, "/proc/%d/psinfo", (int)getpid());
|
2005-08-12 17:34:19 +00:00
|
|
|
|
|
|
|
ifp = fopen(proc_file_name, "r");
|
|
|
|
if (ifp == NULL)
|
2014-10-17 13:42:34 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: Failed to open the process info file:%s\n",
|
|
|
|
proc_file_name);
|
|
|
|
abort();
|
|
|
|
}
|
2005-08-12 17:34:19 +00:00
|
|
|
|
|
|
|
fread(&pinfo, sizeof(pinfo), 1, ifp);
|
|
|
|
fclose(ifp);
|
|
|
|
|
|
|
|
vectors = (char **)pinfo.pr_envp;
|
|
|
|
if (!vectors)
|
2014-10-17 13:42:34 +00:00
|
|
|
{
|
|
|
|
fprintf(stderr, "Error: for some reason, environ == NULL "
|
|
|
|
"during GNUstep base initialization\n"
|
|
|
|
"Please check the linking process\n");
|
|
|
|
abort();
|
|
|
|
}
|
2005-08-12 17:34:19 +00:00
|
|
|
|
|
|
|
/* copy the environment strings */
|
|
|
|
for (count = 0; vectors[count]; count++)
|
|
|
|
;
|
2011-02-19 19:42:42 +00:00
|
|
|
_gnu_noobjc_env = (char**)malloc(sizeof(char*) * (count + 1));
|
2005-08-12 17:34:19 +00:00
|
|
|
if (!_gnu_noobjc_env)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < count; i++)
|
2014-10-17 13:42:34 +00:00
|
|
|
{
|
|
|
|
_gnu_noobjc_env[i] = (char *)strdup(vectors[i]);
|
|
|
|
if (!_gnu_noobjc_env[i])
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
2005-08-12 17:34:19 +00:00
|
|
|
_gnu_noobjc_env[i] = NULL;
|
|
|
|
|
|
|
|
/* get the argument vectors */
|
|
|
|
vectors = (char **)pinfo.pr_argv;
|
|
|
|
if (!vectors)
|
|
|
|
{
|
2005-08-15 04:00:22 +00:00
|
|
|
fprintf(stderr, "Error: psinfo does not return arguments for the current process\n");
|
2005-08-12 17:34:19 +00:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
/* copy the argument strings */
|
|
|
|
for (_gnu_noobjc_argc = 0; vectors[_gnu_noobjc_argc]; _gnu_noobjc_argc++)
|
|
|
|
;
|
2006-05-24 08:27:39 +00:00
|
|
|
_gnu_noobjc_argv
|
2011-02-19 19:42:42 +00:00
|
|
|
= (char**)malloc(sizeof(char*) * (_gnu_noobjc_argc + 1));
|
2005-08-12 17:34:19 +00:00
|
|
|
if (!_gnu_noobjc_argv)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < _gnu_noobjc_argc; i++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_argv[i] = (char *)strdup(vectors[i]);
|
|
|
|
if (!_gnu_noobjc_argv[i])
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_argv[i] = NULL;
|
|
|
|
|
2011-03-17 22:33:31 +00:00
|
|
|
return;
|
|
|
|
#elif defined(__APPLE__)
|
|
|
|
/*
|
|
|
|
* Darwin/Mac OS X provides indirect access to command line arguments and
|
|
|
|
* the environment with functions defined in the C runtime system.
|
|
|
|
*/
|
|
|
|
int i, n;
|
|
|
|
int argc = *_NSGetArgc();
|
|
|
|
char **argv = *_NSGetArgv();
|
|
|
|
char **environ = *_NSGetEnviron();
|
|
|
|
|
|
|
|
/* copy environment */
|
|
|
|
n = 0;
|
|
|
|
while (environ[n] != NULL)
|
|
|
|
n++;
|
|
|
|
_gnu_noobjc_env = (char **)malloc(sizeof(char *) * (n + 1));
|
|
|
|
if (_gnu_noobjc_env == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < n; i++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_env[i] = (char *)strdup(environ[i]);
|
|
|
|
if (_gnu_noobjc_env[i] == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_env[i] = NULL;
|
|
|
|
|
|
|
|
/* copy arguments */
|
|
|
|
_gnu_noobjc_argc = argc;
|
|
|
|
_gnu_noobjc_argv = (char **)malloc(sizeof(char *) * (argc + 1));
|
|
|
|
if (_gnu_noobjc_argv == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
for (i = 0; i < argc; i++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_argv[i] = (char *)strdup(argv[i]);
|
|
|
|
if (_gnu_noobjc_argv[i] == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_argv[i] = NULL;
|
|
|
|
|
2003-06-24 02:45:29 +00:00
|
|
|
return;
|
2004-06-14 22:27:22 +00:00
|
|
|
#else /* !HAVE_KVM_ENV (i.e. HAVE_PROCFS). */
|
1999-07-22 14:17:27 +00:00
|
|
|
/*
|
|
|
|
* Now we have the problem of reading program arguments and
|
|
|
|
* environment. We take the environment from extern char **environ, and
|
2005-02-22 11:22:44 +00:00
|
|
|
* the program arguments from the /proc filesystem.
|
1999-03-10 10:34:56 +00:00
|
|
|
*/
|
1999-07-22 14:17:27 +00:00
|
|
|
extern char **environ;
|
|
|
|
char *proc_file_name = NULL;
|
|
|
|
FILE *ifp;
|
|
|
|
int c;
|
|
|
|
int argument;
|
|
|
|
int length;
|
2005-02-22 11:22:44 +00:00
|
|
|
int position;
|
1999-07-22 14:17:27 +00:00
|
|
|
int env_terms;
|
1999-09-04 05:04:45 +00:00
|
|
|
BOOL stripTrailingNewline = NO;
|
1999-07-22 14:17:27 +00:00
|
|
|
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
|
|
|
extern char *program_invocation_name;
|
|
|
|
#endif /* HAVE_PROGRAM_INVOCATION_NAME */
|
2005-02-22 11:22:44 +00:00
|
|
|
|
|
|
|
// Read environment
|
2000-05-30 17:50:46 +00:00
|
|
|
|
|
|
|
/* NB: This should *never* happen if your compiler tools are
|
|
|
|
sane. But, if you are playing with them, you could break
|
|
|
|
them to the point you get here. :-) */
|
|
|
|
if (environ == NULL)
|
|
|
|
{
|
|
|
|
/* TODO: Try reading environment from /proc before aborting. */
|
2005-02-22 11:22:44 +00:00
|
|
|
fprintf(stderr, "Error: for some reason, environ == NULL "
|
2000-05-30 17:50:46 +00:00
|
|
|
"during GNUstep base initialization\n"
|
|
|
|
"Please check the linking process\n");
|
|
|
|
abort();
|
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
c = 0;
|
|
|
|
while (environ[c] != NULL)
|
|
|
|
c++;
|
|
|
|
env_terms = c;
|
2011-02-19 19:42:42 +00:00
|
|
|
_gnu_noobjc_env = (char**)malloc(sizeof(char*) * (env_terms + 1));
|
1999-07-22 14:17:27 +00:00
|
|
|
if (_gnu_noobjc_env == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
for (c = 0; c < env_terms; c++)
|
|
|
|
{
|
|
|
|
_gnu_noobjc_env[c] = (char *)strdup(environ[c]);
|
|
|
|
if (_gnu_noobjc_env[c] == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_env[c] = NULL;
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
// Read commandline
|
2011-03-07 15:34:06 +00:00
|
|
|
proc_file_name = (char *)malloc(2048);
|
|
|
|
snprintf(proc_file_name, 2048, "/proc/%d/cmdline", (int)getpid());
|
1999-03-10 10:34:56 +00:00
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
/*
|
2005-02-22 11:22:44 +00:00
|
|
|
* We read the /proc file thrice.
|
1999-07-22 14:17:27 +00:00
|
|
|
* First, to know how many arguments there are and allocate memory for them.
|
|
|
|
* Second, to know how long each argument is, and allocate memory accordingly.
|
2005-02-22 11:22:44 +00:00
|
|
|
* Third, to actually copy the arguments into memory.
|
1999-07-22 14:17:27 +00:00
|
|
|
*/
|
|
|
|
_gnu_noobjc_argc = 0;
|
|
|
|
#ifdef HAVE_STRERROR
|
|
|
|
errno = 0;
|
|
|
|
#endif /* HAVE_STRERROR */
|
|
|
|
ifp = fopen(proc_file_name, "r");
|
|
|
|
if (ifp == NULL)
|
|
|
|
goto proc_fs_error;
|
|
|
|
while (1)
|
|
|
|
{
|
|
|
|
c = getc(ifp);
|
|
|
|
if (c == 0)
|
|
|
|
_gnu_noobjc_argc++;
|
|
|
|
else if (c == EOF)
|
|
|
|
break;
|
|
|
|
}
|
2001-04-21 05:55:16 +00:00
|
|
|
#if (CMDLINE_TERMINATED == 0)
|
|
|
|
_gnu_noobjc_argc++;
|
2000-09-30 22:08:21 +00:00
|
|
|
#endif
|
2002-01-24 17:03:04 +00:00
|
|
|
fclose(ifp);
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
/*
|
|
|
|
* Now _gnu_noobcj_argc is the number of arguments;
|
|
|
|
* allocate memory accordingly.
|
|
|
|
*/
|
2011-02-19 19:42:42 +00:00
|
|
|
_gnu_noobjc_argv = (char **)malloc((sizeof(char *)) * (_gnu_noobjc_argc + 1));
|
1999-03-10 10:34:56 +00:00
|
|
|
if (_gnu_noobjc_argv == NULL)
|
1999-07-22 14:17:27 +00:00
|
|
|
goto malloc_error;
|
|
|
|
|
2013-04-14 09:04:40 +00:00
|
|
|
ifp = fopen(proc_file_name,"r");
|
1999-12-21 14:39:56 +00:00
|
|
|
//freopen(proc_file_name, "r", ifp);
|
1999-07-22 14:17:27 +00:00
|
|
|
if (ifp == NULL)
|
1999-03-10 10:34:56 +00:00
|
|
|
{
|
2011-02-19 19:42:42 +00:00
|
|
|
free(_gnu_noobjc_argv);
|
1999-07-22 14:17:27 +00:00
|
|
|
goto proc_fs_error;
|
1999-03-10 10:34:56 +00:00
|
|
|
}
|
1999-07-22 14:17:27 +00:00
|
|
|
argument = 0;
|
|
|
|
length = 0;
|
2001-04-10 03:27:01 +00:00
|
|
|
while (argument < _gnu_noobjc_argc)
|
1999-03-10 10:34:56 +00:00
|
|
|
{
|
1999-07-22 14:17:27 +00:00
|
|
|
c = getc(ifp);
|
|
|
|
length++;
|
2005-02-22 11:22:44 +00:00
|
|
|
if ((c == EOF) || (c == 0)) // End of a parameter
|
|
|
|
{
|
2006-05-24 08:27:39 +00:00
|
|
|
_gnu_noobjc_argv[argument]
|
2011-02-19 19:42:42 +00:00
|
|
|
= (char*)malloc((sizeof(char))*length);
|
1999-07-22 14:17:27 +00:00
|
|
|
if (_gnu_noobjc_argv[argument] == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
argument++;
|
|
|
|
length = 0;
|
2001-04-21 05:55:16 +00:00
|
|
|
if (c == EOF) // End of command line
|
2013-04-14 09:04:40 +00:00
|
|
|
{
|
|
|
|
_gnu_noobjc_argc = argument;
|
|
|
|
break;
|
|
|
|
}
|
1999-07-22 14:17:27 +00:00
|
|
|
}
|
1999-03-10 10:34:56 +00:00
|
|
|
}
|
1999-12-21 14:39:56 +00:00
|
|
|
fclose(ifp);
|
2013-04-14 09:04:40 +00:00
|
|
|
ifp = fopen(proc_file_name,"r");
|
1999-12-21 14:39:56 +00:00
|
|
|
//freopen(proc_file_name, "r", ifp);
|
1999-07-22 14:17:27 +00:00
|
|
|
if (ifp == NULL)
|
|
|
|
{
|
2013-04-14 09:04:40 +00:00
|
|
|
if (0 != _gnu_noobjc_argv)
|
|
|
|
{
|
|
|
|
for (c = 0; c < _gnu_noobjc_argc; c++)
|
|
|
|
{
|
|
|
|
free(_gnu_noobjc_argv[c]);
|
|
|
|
}
|
|
|
|
free(_gnu_noobjc_argv);
|
|
|
|
}
|
1999-07-22 14:17:27 +00:00
|
|
|
goto proc_fs_error;
|
|
|
|
}
|
|
|
|
argument = 0;
|
|
|
|
position = 0;
|
2001-04-12 21:59:19 +00:00
|
|
|
while (argument < _gnu_noobjc_argc)
|
1999-07-22 14:17:27 +00:00
|
|
|
{
|
|
|
|
c = getc(ifp);
|
2005-02-22 11:22:44 +00:00
|
|
|
if ((c == EOF) || (c == 0)) // End of a parameter
|
|
|
|
{
|
1999-09-04 05:04:45 +00:00
|
|
|
if (argument == 0 && position > 0
|
|
|
|
&& _gnu_noobjc_argv[argument][position-1] == '\n')
|
|
|
|
{
|
|
|
|
stripTrailingNewline = YES;
|
|
|
|
}
|
|
|
|
if (stripTrailingNewline == YES && position > 0
|
|
|
|
&& _gnu_noobjc_argv[argument][position-1] == '\n')
|
|
|
|
{
|
|
|
|
position--;
|
|
|
|
}
|
1999-07-22 14:17:27 +00:00
|
|
|
_gnu_noobjc_argv[argument][position] = '\0';
|
|
|
|
argument++;
|
|
|
|
if (c == EOF) // End of command line
|
|
|
|
break;
|
|
|
|
position = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_argv[argument][position] = c;
|
|
|
|
position++;
|
|
|
|
}
|
|
|
|
_gnu_noobjc_argv[argument] = NULL;
|
|
|
|
fclose(ifp);
|
2011-02-19 19:42:42 +00:00
|
|
|
free(proc_file_name);
|
1999-03-10 10:34:56 +00:00
|
|
|
return;
|
1995-08-28 13:36:24 +00:00
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
proc_fs_error:
|
1999-07-22 14:17:27 +00:00
|
|
|
#ifdef HAVE_STRERROR
|
2007-12-19 14:39:44 +00:00
|
|
|
/* Don't care about thread safety of strerror() here as this is only
|
|
|
|
* called in the initial thread and there shouldn't be any other
|
|
|
|
* threads at this point.
|
|
|
|
*/
|
2005-02-22 11:22:44 +00:00
|
|
|
fprintf(stderr, "Couldn't open file %s when starting gnustep-base; %s\n",
|
1999-07-22 14:17:27 +00:00
|
|
|
proc_file_name, strerror(errno));
|
2005-02-22 11:22:44 +00:00
|
|
|
#else /* !HAVE_FUNCTION_STRERROR */
|
|
|
|
fprintf(stderr, "Couldn't open file %s when starting gnustep-base.\n",
|
1999-07-22 14:17:27 +00:00
|
|
|
proc_file_name);
|
|
|
|
#endif /* HAVE_FUNCTION_STRERROR */
|
2005-02-22 11:22:44 +00:00
|
|
|
fprintf(stderr, "Your gnustep-base library is compiled for a kernel supporting the /proc filesystem, but it can't access it.\n");
|
1999-07-22 14:17:27 +00:00
|
|
|
fprintf(stderr, "You should recompile or change your kernel.\n");
|
2013-04-15 06:04:40 +00:00
|
|
|
free(proc_file_name);
|
2005-02-22 11:22:44 +00:00
|
|
|
#ifdef HAVE_PROGRAM_INVOCATION_NAME
|
1999-07-22 14:17:27 +00:00
|
|
|
fprintf(stderr, "We try to go on anyway; but the program will ignore any argument which were passed to it.\n");
|
|
|
|
_gnu_noobjc_argc = 1;
|
2011-02-19 19:42:42 +00:00
|
|
|
_gnu_noobjc_argv = malloc(sizeof(char *) * 2);
|
1999-07-22 14:17:27 +00:00
|
|
|
if (_gnu_noobjc_argv == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
_gnu_noobjc_argv[0] = strdup(program_invocation_name);
|
|
|
|
if (_gnu_noobjc_argv[0] == NULL)
|
|
|
|
goto malloc_error;
|
|
|
|
_gnu_noobjc_argv[1] = NULL;
|
|
|
|
return;
|
|
|
|
#else /* !HAVE_PROGRAM_INVOCATION_NAME */
|
|
|
|
/*
|
|
|
|
* There is really little sense in going on here, because NSBundle
|
|
|
|
* will anyway crash later if we just put something like "_Unknown_"
|
2005-02-22 11:22:44 +00:00
|
|
|
* as the program name.
|
1999-07-22 14:17:27 +00:00
|
|
|
*/
|
|
|
|
abort();
|
|
|
|
#endif /* HAVE_PROGRAM_INVOCATION_NAME */
|
2004-06-14 22:27:22 +00:00
|
|
|
#endif /* !HAVE_KVM_ENV (e.g. HAVE_PROCFS) */
|
2005-02-22 11:22:44 +00:00
|
|
|
malloc_error:
|
2011-02-19 19:42:42 +00:00
|
|
|
fprintf(stderr, "malloc() error when starting gnustep-base.\n");
|
1999-07-22 14:17:27 +00:00
|
|
|
fprintf(stderr, "Free some memory and then re-run the program.\n");
|
1999-03-10 10:34:56 +00:00
|
|
|
abort();
|
1995-08-28 13:36:24 +00:00
|
|
|
}
|
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
static void
|
1999-07-22 14:17:27 +00:00
|
|
|
_gnu_noobjc_free_vars(void)
|
1995-08-28 13:36:24 +00:00
|
|
|
{
|
1999-03-10 10:34:56 +00:00
|
|
|
char **p;
|
2005-02-22 11:22:44 +00:00
|
|
|
|
1999-03-10 10:34:56 +00:00
|
|
|
p = _gnu_noobjc_argv;
|
|
|
|
while (*p)
|
|
|
|
{
|
2011-02-19 19:42:42 +00:00
|
|
|
free(*p);
|
1999-03-10 10:34:56 +00:00
|
|
|
p++;
|
|
|
|
}
|
2011-02-19 19:42:42 +00:00
|
|
|
free(_gnu_noobjc_argv);
|
1999-03-10 10:34:56 +00:00
|
|
|
_gnu_noobjc_argv = 0;
|
1995-08-28 13:36:24 +00:00
|
|
|
|
1999-03-10 10:34:56 +00:00
|
|
|
p = _gnu_noobjc_env;
|
|
|
|
while (*p)
|
|
|
|
{
|
2011-02-19 19:42:42 +00:00
|
|
|
free(*p);
|
1999-03-10 10:34:56 +00:00
|
|
|
p++;
|
|
|
|
}
|
2011-02-19 19:42:42 +00:00
|
|
|
free(_gnu_noobjc_env);
|
1999-03-10 10:34:56 +00:00
|
|
|
_gnu_noobjc_env = 0;
|
1995-08-28 13:36:24 +00:00
|
|
|
}
|
|
|
|
|
1999-03-10 10:34:56 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
2014-10-17 13:42:34 +00:00
|
|
|
if (nil == procLock) procLock = [NSRecursiveLock new];
|
2005-07-15 04:46:17 +00:00
|
|
|
if (self == [NSProcessInfo class]
|
|
|
|
&& !_gnu_processName && !_gnu_arguments && !_gnu_environment)
|
1999-03-10 10:34:56 +00:00
|
|
|
{
|
2012-01-01 07:38:53 +00:00
|
|
|
if (_gnu_noobjc_argv == 0 || _gnu_noobjc_env == 0)
|
2010-06-09 15:03:37 +00:00
|
|
|
{
|
2016-02-15 12:13:37 +00:00
|
|
|
fprintf(stderr, _GNU_MISSING_MAIN_FUNCTION_CALL);
|
2010-06-09 15:03:37 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
1999-07-22 14:17:27 +00:00
|
|
|
_gnu_process_args(_gnu_noobjc_argc, _gnu_noobjc_argv, _gnu_noobjc_env);
|
1999-03-10 10:34:56 +00:00
|
|
|
_gnu_noobjc_free_vars();
|
|
|
|
}
|
1995-08-28 13:36:24 +00:00
|
|
|
}
|
2004-06-14 22:27:22 +00:00
|
|
|
#else /*! HAVE_PROCFS !HAVE_LOAD_METHOD !HAVE_KVM_ENV */
|
1995-08-28 13:36:24 +00:00
|
|
|
|
2016-03-09 13:16:16 +00:00
|
|
|
#ifdef _WIN32
|
2000-09-15 22:06:01 +00:00
|
|
|
/* For WindowsAPI Library, we know the global variables (argc, etc) */
|
1999-07-22 14:17:27 +00:00
|
|
|
+ (void) initialize
|
1997-09-13 17:52:31 +00:00
|
|
|
{
|
2014-10-17 13:42:34 +00:00
|
|
|
if (nil == procLock) procLock = [NSRecursiveLock new];
|
2005-07-15 04:46:17 +00:00
|
|
|
if (self == [NSProcessInfo class]
|
|
|
|
&& !_gnu_processName && !_gnu_arguments && !_gnu_environment)
|
|
|
|
{
|
|
|
|
_gnu_process_args(__argc, __argv, _environ);
|
|
|
|
}
|
1997-09-13 17:52:31 +00:00
|
|
|
}
|
2002-12-29 02:00:04 +00:00
|
|
|
#elif defined(__BEOS__)
|
|
|
|
|
|
|
|
extern int __libc_argc;
|
|
|
|
extern char **__libc_argv;
|
|
|
|
+ (void) initialize
|
|
|
|
{
|
2014-10-17 13:42:34 +00:00
|
|
|
if (nil == procLock) procLock = [NSRecursiveLock new];
|
2005-07-15 04:46:17 +00:00
|
|
|
if (self == [NSProcessInfo class]
|
|
|
|
&& !_gnu_processName && !_gnu_arguments && !_gnu_environment)
|
|
|
|
{
|
|
|
|
_gnu_process_args(__libc_argc, __libc_argv, environ);
|
|
|
|
}
|
2002-12-29 02:00:04 +00:00
|
|
|
}
|
|
|
|
|
1995-08-16 15:56:33 +00:00
|
|
|
#else
|
2014-10-17 13:42:34 +00:00
|
|
|
+ (void) initialize
|
|
|
|
{
|
|
|
|
if (nil == procLock) procLock = [NSRecursiveLock new];
|
|
|
|
}
|
2000-06-30 22:42:48 +00:00
|
|
|
#ifndef GS_PASS_ARGUMENTS
|
1995-08-16 15:56:33 +00:00
|
|
|
#undef main
|
2010-06-09 15:19:01 +00:00
|
|
|
/* The gnustep_base_user_main function is declared 'weak' so that the linker
|
|
|
|
* should actually use the one compiled as the program's 'main' function.
|
|
|
|
* The internal version gets called only if the program does not implement
|
|
|
|
* the function (ie the prgram was compiled with the wrong version of
|
|
|
|
* GSConfig.h included/imported). The other possible reason for the internal
|
|
|
|
* function to be called would be a compiler/linker issue (eg 'weak' not
|
|
|
|
* supported).
|
|
|
|
*/
|
2010-06-09 15:03:37 +00:00
|
|
|
int gnustep_base_user_main () __attribute__((weak));
|
|
|
|
int gnustep_base_user_main (int argc, char *argv[], char *env[])
|
|
|
|
{
|
|
|
|
fprintf(stderr, "\nGNUSTEP Internal Error:\n"
|
|
|
|
"The GNUstep function to establish the argv and environment variables could\n"
|
|
|
|
"not find the main function of your program.\n"
|
|
|
|
"Perhaps your program failed to #include <Foundation/NSObject.h> or\n"
|
2010-06-09 15:19:01 +00:00
|
|
|
"<Foundation/Foundation.h> (or included/imported a different version of the\n"
|
|
|
|
"header from the one supplied with this copy of the gnustep-base library)?\n"
|
2010-06-09 15:03:37 +00:00
|
|
|
"If that is not the case, Please report the error to bug-gnustep@gnu.org.\n");
|
|
|
|
exit(1);
|
|
|
|
}
|
1995-08-16 15:56:33 +00:00
|
|
|
int main(int argc, char *argv[], char *env[])
|
|
|
|
{
|
2002-03-12 15:25:37 +00:00
|
|
|
#ifdef NeXT_RUNTIME
|
|
|
|
/* This memcpy has to be done before the first message is sent to any
|
|
|
|
constant string object. See Apple Radar 2870817 */
|
|
|
|
memcpy(&_NSConstantStringClassReference,
|
2002-03-13 16:49:56 +00:00
|
|
|
objc_getClass(STRINGIFY(NXConstantString)),
|
2002-03-12 15:25:37 +00:00
|
|
|
sizeof(_NSConstantStringClassReference));
|
|
|
|
#endif
|
|
|
|
|
1995-08-16 15:56:33 +00:00
|
|
|
_gnu_process_args(argc, argv, env);
|
|
|
|
|
|
|
|
/* Call the user defined main function */
|
1999-07-22 14:17:27 +00:00
|
|
|
return gnustep_base_user_main(argc, argv, env);
|
1995-08-16 15:56:33 +00:00
|
|
|
}
|
2000-06-30 22:42:48 +00:00
|
|
|
#endif /* !GS_PASS_ARGUMENTS */
|
2016-03-09 13:16:16 +00:00
|
|
|
#endif /* _WIN32 */
|
1999-07-22 14:17:27 +00:00
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
#endif /* HAS_LOAD_METHOD && HAS_PROCFS */
|
1995-08-16 15:56:33 +00:00
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
+ (NSProcessInfo *) processInfo
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-08-16 16:14:11 +00:00
|
|
|
// Check if the main() function was successfully called
|
1998-05-29 15:25:41 +00:00
|
|
|
// We can't use NSAssert, which calls NSLog, which calls NSProcessInfo...
|
|
|
|
if (!(_gnu_processName && _gnu_arguments && _gnu_environment))
|
|
|
|
{
|
2016-02-15 12:13:37 +00:00
|
|
|
fprintf(stderr, _GNU_MISSING_MAIN_FUNCTION_CALL);
|
2010-06-09 15:03:37 +00:00
|
|
|
exit(1);
|
1998-05-29 15:25:41 +00:00
|
|
|
}
|
1995-08-16 15:47:12 +00:00
|
|
|
|
1995-08-16 16:14:11 +00:00
|
|
|
if (!_gnu_sharedProcessInfoObject)
|
2002-01-24 17:03:04 +00:00
|
|
|
{
|
|
|
|
_gnu_sharedProcessInfoObject = [[_NSConcreteProcessInfo alloc] init];
|
2014-10-17 13:42:34 +00:00
|
|
|
[procLock lock];
|
2010-02-14 10:48:10 +00:00
|
|
|
if (mySet != nil)
|
|
|
|
{
|
|
|
|
NSEnumerator *e = [mySet objectEnumerator];
|
|
|
|
NSMutableSet *s = [_gnu_sharedProcessInfoObject debugSet];
|
|
|
|
id o;
|
|
|
|
|
|
|
|
while ((o = [e nextObject]) != nil)
|
|
|
|
{
|
|
|
|
[s addObject: o];
|
|
|
|
}
|
|
|
|
[mySet release];
|
|
|
|
mySet = nil;
|
|
|
|
}
|
2014-10-17 13:42:34 +00:00
|
|
|
[procLock unlock];
|
2002-01-24 17:03:04 +00:00
|
|
|
}
|
2010-02-14 10:48:10 +00:00
|
|
|
|
1995-08-16 16:14:11 +00:00
|
|
|
return _gnu_sharedProcessInfoObject;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2007-08-02 09:36:38 +00:00
|
|
|
+ (BOOL) _exists: (int)pid
|
|
|
|
{
|
|
|
|
if (pid > 0)
|
|
|
|
{
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2007-08-02 09:53:30 +00:00
|
|
|
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION,0,pid);
|
2007-08-02 09:36:38 +00:00
|
|
|
if (h == NULL && GetLastError() != ERROR_ACCESS_DENIED)
|
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
CloseHandle(h);
|
|
|
|
#else
|
2007-08-02 11:18:56 +00:00
|
|
|
if (kill(pid, 0) < 0 && errno == ESRCH)
|
2007-08-02 09:36:38 +00:00
|
|
|
{
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
- (NSArray *) arguments
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-11-03 16:12:07 +00:00
|
|
|
return _gnu_arguments;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
- (NSDictionary *) environment
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1995-11-03 16:12:07 +00:00
|
|
|
return _gnu_environment;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2002-04-08 15:32:52 +00:00
|
|
|
- (NSString *) globallyUniqueString
|
|
|
|
{
|
2002-08-08 09:11:50 +00:00
|
|
|
static unsigned long counter = 0;
|
2006-08-26 06:27:54 +00:00
|
|
|
unsigned long count;
|
2002-08-08 09:11:50 +00:00
|
|
|
static NSString *host = nil;
|
2014-10-17 13:42:34 +00:00
|
|
|
NSString *thost = nil;
|
2016-04-17 15:18:43 +00:00
|
|
|
static int pid = 0;
|
|
|
|
int tpid = 0;
|
2002-08-08 09:11:50 +00:00
|
|
|
static unsigned long start;
|
2002-04-08 15:32:52 +00:00
|
|
|
|
2014-10-17 13:42:34 +00:00
|
|
|
/* We obtain the host name and pid outside the locked region in case
|
|
|
|
* the lookup is slow or indirectly calls this method fromm another
|
|
|
|
* thread (as unlikely as that is ... some subclass/category could
|
|
|
|
* do it).
|
|
|
|
*/
|
|
|
|
if (nil == host)
|
|
|
|
{
|
|
|
|
thost = [[self hostName] stringByReplacingString: @"." withString: @"_"];
|
|
|
|
tpid = [self processIdentifier];
|
|
|
|
}
|
|
|
|
[procLock lock];
|
|
|
|
if (nil == host)
|
2002-08-07 16:15:01 +00:00
|
|
|
{
|
2010-12-27 07:03:50 +00:00
|
|
|
start = (unsigned long)GSPrivateTimeNow();
|
2014-10-17 13:42:34 +00:00
|
|
|
ASSIGN(host, thost);
|
|
|
|
pid = tpid;
|
2002-08-07 16:15:01 +00:00
|
|
|
}
|
|
|
|
count = counter++;
|
2014-10-17 13:42:34 +00:00
|
|
|
[procLock unlock];
|
2002-04-08 15:32:52 +00:00
|
|
|
|
2005-02-22 11:22:44 +00:00
|
|
|
// $$$ The format of the string is not specified by the OpenStep
|
2002-08-07 16:15:01 +00:00
|
|
|
// specification.
|
2002-08-08 09:11:50 +00:00
|
|
|
return [NSString stringWithFormat: @"%@_%x_%lx_%lx",
|
|
|
|
host, pid, start, count];
|
2002-04-08 15:32:52 +00:00
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
- (NSString *) hostName
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
2005-02-22 11:22:44 +00:00
|
|
|
if (!_gnu_hostName)
|
1995-11-03 16:12:07 +00:00
|
|
|
{
|
2014-04-19 01:34:48 +00:00
|
|
|
_gnu_hostName = [[NSHost _myHostName] copy];
|
1995-11-03 16:12:07 +00:00
|
|
|
}
|
|
|
|
return _gnu_hostName;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2006-10-03 13:35:50 +00:00
|
|
|
static void determineOperatingSystem()
|
2001-07-15 09:08:27 +00:00
|
|
|
{
|
2006-10-03 13:35:50 +00:00
|
|
|
if (_operatingSystem == 0)
|
2002-04-08 15:32:52 +00:00
|
|
|
{
|
2006-10-03 14:49:01 +00:00
|
|
|
NSString *os = nil;
|
|
|
|
BOOL parseOS = YES;
|
2002-04-08 15:32:52 +00:00
|
|
|
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2006-10-03 13:35:50 +00:00
|
|
|
OSVERSIONINFOW osver;
|
|
|
|
|
|
|
|
osver.dwOSVersionInfoSize = sizeof(osver);
|
|
|
|
GetVersionExW (&osver);
|
|
|
|
/* Hmm, we could use this to determine operating system version, but
|
|
|
|
* that would not distinguish between mingw and cygwin, so we just
|
|
|
|
* use the information from NSBundle and only get the version info
|
|
|
|
* here.
|
|
|
|
*/
|
2021-08-10 16:49:29 +00:00
|
|
|
_operatingSystemVersion = [[NSString alloc] initWithFormat: @"%lu.%lu",
|
2006-10-03 13:35:50 +00:00
|
|
|
osver.dwMajorVersion, osver.dwMinorVersion];
|
|
|
|
#else
|
|
|
|
#if defined(HAVE_SYS_UTSNAME_H)
|
|
|
|
struct utsname uts;
|
|
|
|
|
|
|
|
/* The system supports uname, so we can use it rather than the
|
|
|
|
* value determined at configure/compile time.
|
|
|
|
* That's good if the binary is running on a system other than
|
|
|
|
* the one it was built for (rare, but can happen).
|
|
|
|
*/
|
2014-03-25 23:06:00 +00:00
|
|
|
if (!(uname(&uts) < 0))
|
2006-09-21 08:49:02 +00:00
|
|
|
{
|
2006-10-03 13:35:50 +00:00
|
|
|
os = [NSString stringWithCString: uts.sysname encoding: [NSString defaultCStringEncoding]];
|
2006-10-03 14:49:01 +00:00
|
|
|
os = [os lowercaseString];
|
2006-10-03 13:42:53 +00:00
|
|
|
/* Get the operating system version ... usually the version string
|
|
|
|
* is pretty horrible, and the kernel release string actually
|
|
|
|
* makes more sense.
|
|
|
|
*/
|
2006-10-03 13:35:50 +00:00
|
|
|
_operatingSystemVersion = [[NSString alloc]
|
2006-10-03 13:42:53 +00:00
|
|
|
initWithCString: uts.release
|
2006-10-03 13:35:50 +00:00
|
|
|
encoding: [NSString defaultCStringEncoding]];
|
2006-10-03 14:49:01 +00:00
|
|
|
|
|
|
|
/* Hack for sunos/solaris ... sunos version 5 is solaris
|
|
|
|
*/
|
|
|
|
if ([os isEqualToString: @"sunos"] == YES
|
|
|
|
&& [_operatingSystemVersion intValue] > 4)
|
|
|
|
{
|
|
|
|
os = @"solaris";
|
|
|
|
}
|
2006-09-21 08:49:02 +00:00
|
|
|
}
|
2006-10-03 13:35:50 +00:00
|
|
|
#endif /* HAVE_SYS_UTSNAME_H */
|
2016-03-09 13:16:16 +00:00
|
|
|
#endif /* _WIN32 */
|
2006-10-03 13:35:50 +00:00
|
|
|
|
|
|
|
if (_operatingSystemVersion == nil)
|
2002-04-08 15:32:52 +00:00
|
|
|
{
|
2006-10-03 13:35:50 +00:00
|
|
|
NSWarnFLog(@"Unable to determine system version, using 0.0");
|
|
|
|
_operatingSystemVersion = @"0.0";
|
2002-04-08 15:32:52 +00:00
|
|
|
}
|
2006-09-21 08:49:02 +00:00
|
|
|
|
2006-10-03 14:49:01 +00:00
|
|
|
while (parseOS == YES)
|
2006-09-21 08:49:02 +00:00
|
|
|
{
|
2006-10-03 14:49:01 +00:00
|
|
|
NSString *fallback = [NSBundle _gnustep_target_os];
|
|
|
|
|
|
|
|
if (os == nil)
|
|
|
|
{
|
|
|
|
os = fallback;
|
|
|
|
}
|
|
|
|
parseOS = NO;
|
|
|
|
|
|
|
|
if ([os hasPrefix: @"linux"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"GSGNULinuxOperatingSystem";
|
|
|
|
_operatingSystem = GSGNULinuxOperatingSystem;
|
|
|
|
}
|
2021-03-12 14:51:19 +00:00
|
|
|
else if ([os hasPrefix: @"mingw"] == YES
|
|
|
|
|| [os isEqualToString: @"windows"] == YES)
|
2006-10-03 14:49:01 +00:00
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSWindowsNTOperatingSystem";
|
|
|
|
_operatingSystem = NSWindowsNTOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os isEqualToString: @"cygwin"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"GSCygwinOperatingSystem";
|
|
|
|
_operatingSystem = GSCygwinOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"bsd"] == YES
|
|
|
|
|| [os hasPrefix: @"freebsd"] == YES
|
|
|
|
|| [os hasPrefix: @"netbsd"] == YES
|
|
|
|
|| [os hasPrefix: @"openbsd"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"GSBSDOperatingSystem";
|
|
|
|
_operatingSystem = GSBSDOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"beos"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"GSBeOperatingSystem";
|
|
|
|
_operatingSystem = GSBeOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"darwin"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSMACHOperatingSystem";
|
|
|
|
_operatingSystem = NSMACHOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"solaris"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSSolarisOperatingSystem";
|
|
|
|
_operatingSystem = NSSolarisOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"hpux"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSHPUXOperatingSystem";
|
|
|
|
_operatingSystem = NSHPUXOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"sunos"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSSunOSOperatingSystem";
|
|
|
|
_operatingSystem = NSSunOSOperatingSystem;
|
|
|
|
}
|
|
|
|
else if ([os hasPrefix: @"osf"] == YES)
|
|
|
|
{
|
|
|
|
_operatingSystemName = @"NSOSF1OperatingSystem";
|
|
|
|
_operatingSystem = NSOSF1OperatingSystem;
|
|
|
|
}
|
|
|
|
if (_operatingSystem == 0 && [os isEqual: fallback] == NO)
|
|
|
|
{
|
|
|
|
os = fallback;
|
|
|
|
parseOS = YES; // Try again with fallback
|
|
|
|
}
|
2006-09-21 08:49:02 +00:00
|
|
|
}
|
2006-10-03 14:49:01 +00:00
|
|
|
|
|
|
|
if (_operatingSystem == 0)
|
2006-09-21 08:49:02 +00:00
|
|
|
{
|
2006-10-03 13:35:50 +00:00
|
|
|
NSWarnFLog(@"Unable to determine O/S ... assuming GNU/Linux");
|
|
|
|
_operatingSystemName = @"GSGNULinuxOperatingSystem";
|
|
|
|
_operatingSystem = GSGNULinuxOperatingSystem;
|
2006-09-21 08:49:02 +00:00
|
|
|
}
|
2002-04-08 15:32:52 +00:00
|
|
|
}
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2009-02-23 20:42:32 +00:00
|
|
|
- (NSUInteger) operatingSystem
|
2006-10-03 13:35:50 +00:00
|
|
|
{
|
|
|
|
if (_operatingSystem == 0)
|
|
|
|
{
|
|
|
|
determineOperatingSystem();
|
|
|
|
}
|
|
|
|
return _operatingSystem;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString*) operatingSystemName
|
|
|
|
{
|
|
|
|
if (_operatingSystemName == 0)
|
|
|
|
{
|
|
|
|
determineOperatingSystem();
|
|
|
|
}
|
|
|
|
return _operatingSystemName;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) operatingSystemVersionString
|
|
|
|
{
|
|
|
|
if (_operatingSystemVersion == nil)
|
|
|
|
{
|
|
|
|
determineOperatingSystem();
|
|
|
|
}
|
|
|
|
return _operatingSystemVersion;
|
|
|
|
}
|
|
|
|
|
2002-04-08 15:32:52 +00:00
|
|
|
- (int) processIdentifier
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
1999-05-06 05:49:55 +00:00
|
|
|
int pid;
|
|
|
|
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
1999-06-02 04:19:41 +00:00
|
|
|
pid = (int)GetCurrentProcessId();
|
1999-05-06 05:49:55 +00:00
|
|
|
#else
|
|
|
|
pid = (int)getpid();
|
|
|
|
#endif
|
2002-04-08 15:32:52 +00:00
|
|
|
return pid;
|
|
|
|
}
|
1999-05-06 05:49:55 +00:00
|
|
|
|
2002-04-08 15:32:52 +00:00
|
|
|
- (NSString *) processName
|
|
|
|
{
|
|
|
|
return _gnu_processName;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
1999-07-22 14:17:27 +00:00
|
|
|
- (void) setProcessName: (NSString *)newName
|
1995-08-16 15:47:12 +00:00
|
|
|
{
|
2008-11-13 10:09:50 +00:00
|
|
|
if (newName && [newName length])
|
|
|
|
{
|
|
|
|
[_gnu_processName autorelease];
|
|
|
|
_gnu_processName = [newName copyWithZone: [self zone]];
|
|
|
|
}
|
1995-08-16 16:14:11 +00:00
|
|
|
return;
|
1995-08-16 15:47:12 +00:00
|
|
|
}
|
|
|
|
|
2008-06-06 13:57:06 +00:00
|
|
|
- (NSUInteger) processorCount
|
|
|
|
{
|
2008-11-13 10:09:50 +00:00
|
|
|
static NSUInteger procCount = 0;
|
|
|
|
static BOOL beenHere = NO;
|
|
|
|
|
|
|
|
if (beenHere == NO)
|
|
|
|
{
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2008-11-13 10:09:50 +00:00
|
|
|
SYSTEM_INFO info;
|
|
|
|
|
|
|
|
GetSystemInfo(&info);
|
|
|
|
return info.dwNumberOfProcessors;
|
|
|
|
#elif defined(_SC_NPROCESSORS_CONF)
|
|
|
|
procCount = sysconf(_SC_NPROCESSORS_CONF);
|
2008-11-13 14:28:56 +00:00
|
|
|
#elif defined(HAVE_SYSCTLBYNAME)
|
2008-11-14 21:59:13 +00:00
|
|
|
int val;
|
|
|
|
size_t len = sizeof(val);
|
2008-11-13 14:28:56 +00:00
|
|
|
|
2008-11-13 17:58:13 +00:00
|
|
|
if (sysctlbyname("hw.ncpu", &val, &len, 0, 0) == 0)
|
2008-11-13 14:28:56 +00:00
|
|
|
{
|
|
|
|
procCount = val;
|
|
|
|
}
|
2008-11-13 10:09:50 +00:00
|
|
|
#elif defined(HAVE_PROCFS)
|
|
|
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
|
|
|
|
|
if ([fileManager fileExistsAtPath: @"/proc/cpuinfo"])
|
|
|
|
{
|
|
|
|
NSString *cpuInfo;
|
|
|
|
NSArray *a;
|
|
|
|
unsigned i;
|
|
|
|
|
|
|
|
cpuInfo = [NSString stringWithContentsOfFile: @"/proc/cpuinfo"];
|
|
|
|
a = [cpuInfo componentsSeparatedByCharactersInSet:
|
|
|
|
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
|
// syntax is processor : #
|
|
|
|
// count up each one
|
|
|
|
for (i = 0; i < [a count]; ++i)
|
|
|
|
{
|
|
|
|
if ([[a objectAtIndex: i] isEqualToString: @"processor"])
|
|
|
|
{
|
|
|
|
if (((i+1) < [a count])
|
|
|
|
&& [[a objectAtIndex: i+1] isEqualToString: @":"])
|
|
|
|
{
|
|
|
|
procCount++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#warning "no known way to determine number of processors on this system"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
beenHere = YES;
|
|
|
|
if (procCount == 0)
|
|
|
|
{
|
|
|
|
NSLog(@"Cannot determine processor count.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return procCount;
|
2008-06-06 13:57:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (NSUInteger) activeProcessorCount
|
|
|
|
{
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2008-11-13 10:09:50 +00:00
|
|
|
SYSTEM_INFO info;
|
|
|
|
int index;
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
GetSystemInfo(&info);
|
|
|
|
for (index = 0; index < 32; index++)
|
|
|
|
{
|
|
|
|
if (info.dwActiveProcessorMask & (1<<index))
|
|
|
|
{
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
#elif defined(_SC_NPROCESSORS_ONLN)
|
|
|
|
return sysconf(_SC_NPROCESSORS_ONLN);
|
2008-11-13 14:28:56 +00:00
|
|
|
#elif defined(HAVE_SYSCTLBYNAME)
|
2008-11-14 21:59:13 +00:00
|
|
|
int val;
|
|
|
|
size_t len = sizeof(val);
|
2008-11-13 14:28:56 +00:00
|
|
|
|
2008-11-13 17:58:13 +00:00
|
|
|
if (sysctlbyname("kern.smp.cpus", &val, &len, 0, 0) == 0)
|
2008-11-14 21:59:13 +00:00
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
else if (sysctlbyname("hw.activecpu", &val, &len, 0, 0) == 0)
|
2008-11-13 14:28:56 +00:00
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
return [self processorCount];
|
2008-11-13 10:09:50 +00:00
|
|
|
#else
|
|
|
|
return [self processorCount];
|
|
|
|
#endif
|
2008-06-06 13:57:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
- (unsigned long long) physicalMemory
|
|
|
|
{
|
2008-11-13 10:09:50 +00:00
|
|
|
static NSUInteger availMem = 0;
|
|
|
|
static BOOL beenHere = NO;
|
|
|
|
|
|
|
|
if (beenHere == NO)
|
|
|
|
{
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2008-11-13 10:09:50 +00:00
|
|
|
MEMORYSTATUSEX memory;
|
|
|
|
|
|
|
|
memory.dwLength = sizeof(memory);
|
|
|
|
GlobalMemoryStatusEx(&memory);
|
|
|
|
return memory.ullTotalPhys;
|
|
|
|
#elif defined(_SC_PHYS_PAGES)
|
|
|
|
availMem = sysconf(_SC_PHYS_PAGES) * NSPageSize();
|
2008-11-13 14:28:56 +00:00
|
|
|
#elif defined(HAVE_SYSCTLBYNAME)
|
|
|
|
long val;
|
|
|
|
size_t len = val;
|
|
|
|
|
2008-11-13 17:58:13 +00:00
|
|
|
if (sysctlbyname("hw.physmem", &val, &len, 0, 0) == 0)
|
2008-11-13 14:28:56 +00:00
|
|
|
{
|
|
|
|
availMem = val;
|
|
|
|
}
|
2008-11-13 10:09:50 +00:00
|
|
|
#elif defined(HAVE_PROCFS)
|
|
|
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
|
|
|
|
|
if ([fileManager fileExistsAtPath: @"/proc/meminfo"])
|
|
|
|
{
|
|
|
|
NSString *memInfo;
|
|
|
|
NSString *s;
|
|
|
|
NSArray *a;
|
|
|
|
NSRange r;
|
|
|
|
|
|
|
|
memInfo = [NSString stringWithContentsOfFile: @"/proc/meminfo"];
|
|
|
|
r = [memInfo rangeOfString: @"MemTotal:"];
|
|
|
|
|
|
|
|
if (r.location == NSNotFound)
|
|
|
|
{
|
|
|
|
NSLog(@"Cannot determine amount of physical memory.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
s = [[memInfo substringFromIndex: (r.location + r.length)]
|
|
|
|
stringByTrimmingCharactersInSet:
|
|
|
|
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
|
|
|
|
a = [s componentsSeparatedByString: @" "];
|
|
|
|
s = [a objectAtIndex: 0];
|
|
|
|
availMem = (NSUInteger)[s longLongValue];
|
|
|
|
availMem *= NSPageSize();
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#warning "no known way to determine amount of memory on this system"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
beenHere = YES;
|
|
|
|
if (availMem == 0)
|
|
|
|
{
|
|
|
|
NSLog(@"Cannot determine amount of physical memory.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return availMem;
|
2008-06-06 13:57:06 +00:00
|
|
|
}
|
2008-11-13 10:09:50 +00:00
|
|
|
|
2017-06-20 23:59:31 +00:00
|
|
|
- (NSUInteger) systemUptime
|
|
|
|
{
|
|
|
|
NSUInteger uptime = 0;
|
|
|
|
|
|
|
|
#if defined(_WIN32)
|
2017-07-07 08:50:10 +00:00
|
|
|
|
|
|
|
#if _WIN32_WINNT < 0x0600 /* less than Vista */
|
|
|
|
uptime = GetTickCount() / 1000;
|
|
|
|
#else
|
2017-06-20 23:59:31 +00:00
|
|
|
uptime = GetTickCount64() / 1000;
|
2017-07-07 08:50:10 +00:00
|
|
|
#endif
|
|
|
|
|
2017-06-20 23:59:31 +00:00
|
|
|
#elif defined(HAVE_SYSCTLBYNAME)
|
|
|
|
struct timeval tval;
|
|
|
|
size_t len = sizeof(tval);
|
|
|
|
|
|
|
|
if (sysctlbyname("kern.boottime", &tval, &len, 0, 0) == 0)
|
|
|
|
{
|
|
|
|
uptime = tval.tv_sec;
|
|
|
|
}
|
|
|
|
#elif defined(HAVE_PROCFS)
|
|
|
|
NSFileManager *fileManager = [NSFileManager defaultManager];
|
|
|
|
|
|
|
|
if ([fileManager fileExistsAtPath: @"/proc/uptime"])
|
|
|
|
{
|
|
|
|
NSString *uptimeContent = [NSString
|
|
|
|
stringWithContentsOfFile: @"/proc/uptime"];
|
|
|
|
NSString *uptimeString = [[uptimeContent
|
|
|
|
componentsSeparatedByString:@" "] objectAtIndex:0];
|
|
|
|
uptime = [uptimeString intValue];
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
#warning "no known way to determine uptime on this system"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if (uptime == 0)
|
|
|
|
{
|
|
|
|
NSLog(@"Cannot determine uptime.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return uptime;
|
|
|
|
}
|
|
|
|
|
2017-06-23 16:09:35 +00:00
|
|
|
- (void) enableSuddenTermination
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) disableSuddenTermination
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (id) beginActivityWithOptions: (NSActivityOptions)options
|
|
|
|
reason: (NSString *)reason
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return nil;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) endActivity:(id<NSObject>)activity
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) performActivityWithOptions:(NSActivityOptions)options
|
|
|
|
reason: (NSString *)reason
|
|
|
|
usingBlock: (GSPerformActivityBlock)block
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void) performExpiringActivityWithReason: (NSString *)reason
|
|
|
|
usingBlock: (GSPerformExpiringActivityBlock)block
|
|
|
|
{
|
|
|
|
// FIXME: unimplemented
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
1995-08-16 15:47:12 +00:00
|
|
|
@end
|
1995-08-16 15:56:33 +00:00
|
|
|
|
2009-10-12 14:38:49 +00:00
|
|
|
void
|
|
|
|
GSInitializeProcess(int argc, char **argv, char **envp)
|
|
|
|
{
|
|
|
|
[NSProcessInfo class];
|
2014-10-17 13:42:34 +00:00
|
|
|
[procLock lock];
|
2009-10-12 14:38:49 +00:00
|
|
|
fallbackInitialisation = YES;
|
|
|
|
_gnu_process_args(argc, argv, envp);
|
2014-10-17 13:42:34 +00:00
|
|
|
[procLock unlock];
|
2009-10-12 14:38:49 +00:00
|
|
|
}
|
|
|
|
|
2019-09-25 10:11:50 +00:00
|
|
|
#ifdef __ANDROID__
|
2024-02-01 15:32:07 +00:00
|
|
|
static NSString *
|
|
|
|
_NSStringFromJString(JNIEnv *env, jstring jstr)
|
|
|
|
{
|
|
|
|
const jchar *unichars = (*env)->GetStringChars(env, jstr, NULL);
|
|
|
|
jsize len = (*env)->GetStringLength(env, jstr);
|
|
|
|
NSString *result = [NSString stringWithCharacters:unichars length:len];
|
|
|
|
(*env)->ReleaseStringChars(env, jstr, unichars);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-09-25 10:11:50 +00:00
|
|
|
void
|
|
|
|
GSInitializeProcessAndroid(JNIEnv *env, jobject context)
|
|
|
|
{
|
2024-02-01 15:32:07 +00:00
|
|
|
jclass contextCls = (*env)->GetObjectClass(env, context);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, contextCls, "L/android/content/Context;");
|
2019-09-25 10:11:50 +00:00
|
|
|
|
|
|
|
// get package code path (path to APK)
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID packageCodePathMethod = (*env)->GetMethodID(env, contextCls, "getPackageCodePath", "()Ljava/lang/String;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, packageCodePathMethod);
|
2019-09-25 10:11:50 +00:00
|
|
|
jstring packageCodePathJava = (*env)->CallObjectMethod(env, context, packageCodePathMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, packageCodePathJava);
|
|
|
|
|
2019-09-25 10:11:50 +00:00
|
|
|
const char *packageCodePath = (*env)->GetStringUTFChars(env, packageCodePathJava, NULL);
|
|
|
|
|
|
|
|
// get package name
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID packageNameMethod = (*env)->GetMethodID(env, contextCls, "getPackageName", "()Ljava/lang/String;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, packageNameMethod);
|
2019-09-25 10:11:50 +00:00
|
|
|
jstring packageNameJava = (*env)->CallObjectMethod(env, context, packageNameMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, packageNameJava);
|
|
|
|
|
2019-09-25 10:11:50 +00:00
|
|
|
const char *packageName = (*env)->GetStringUTFChars(env, packageNameJava, NULL);
|
|
|
|
|
|
|
|
// create fake executable path consisting of package code path (without .apk)
|
|
|
|
// and package name as executable
|
|
|
|
char *lastSlash = strrchr(packageCodePath, '/');
|
|
|
|
if (lastSlash == NULL)
|
|
|
|
{
|
|
|
|
lastSlash = (char *)packageCodePath + strlen(packageCodePath);
|
|
|
|
}
|
|
|
|
char *arg0;
|
|
|
|
asprintf(&arg0, "%.*s/%s", (int)(lastSlash - packageCodePath), packageCodePath, packageName);
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
|
|
|
|
// get current locale
|
|
|
|
jclass localeCls = (*env)->FindClass(env, "java/util/Locale");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, localeCls, "Ljava/util/Locale;");
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID localeDefaultMethod = (*env)->GetStaticMethodID(env, localeCls, "getDefault", "()Ljava/util/Locale;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, localeDefaultMethod);
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID localeIdMethod = (*env)->GetMethodID(env, localeCls, "toLanguageTag", "()Ljava/lang/String;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, localeIdMethod);
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
jobject localeObj = (*env)->CallStaticObjectMethod(env, localeCls, localeDefaultMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, localeObj);
|
2024-02-01 15:32:07 +00:00
|
|
|
jstring localeIdJava = (*env)->CallObjectMethod(env, localeObj, localeIdMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, localeIdJava);
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
const char *localeIdOrig = (*env)->GetStringUTFChars(env, localeIdJava, NULL);
|
|
|
|
|
|
|
|
// Android uses dashes as delimiters (e.g "en-US"), but we expect underscores
|
|
|
|
char *localeId = strdup(localeIdOrig);
|
|
|
|
for (int i = 0; localeId[i]; i++) {
|
|
|
|
if (localeId[i] == '-') {
|
|
|
|
localeId[i] = '_';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-07 14:26:16 +00:00
|
|
|
char *localeList = NULL;
|
|
|
|
#if __ANDROID_API__ >= 24
|
|
|
|
// get locales ordered by user preference
|
|
|
|
jclass localeListCls = (*env)->FindClass(env, "android/os/LocaleList");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, localeListCls, "L/android/os/LocaleList;");
|
2024-08-07 14:26:16 +00:00
|
|
|
jmethodID localeListGetDefaultMethod = (*env)->GetStaticMethodID(env, localeListCls, "getDefault", "()Landroid/os/LocaleList;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, localeListGetDefaultMethod);
|
2024-08-07 14:26:16 +00:00
|
|
|
|
2024-08-20 17:19:59 +00:00
|
|
|
jobject localeListObj = (*env)->CallStaticObjectMethod(env, localeListCls, localeListGetDefaultMethod);
|
|
|
|
GS_JNI_CHECK(env, localeListObj);
|
2024-08-07 14:26:16 +00:00
|
|
|
|
2024-08-20 17:19:59 +00:00
|
|
|
// Retrieve string representation of the locale list
|
|
|
|
jmethodID localeListToLanguageTagsMethod = (*env)->GetMethodID(env, localeListCls, "toLanguageTags", "()Ljava/lang/String;");
|
|
|
|
GS_JNI_METH_CHECK(env, localeListToLanguageTagsMethod);
|
|
|
|
jstring localeListJava = (*env)->CallObjectMethod(env, localeListObj, localeListToLanguageTagsMethod);
|
|
|
|
GS_JNI_CHECK(env, localeListJava);
|
|
|
|
|
|
|
|
const char *localeListOrig = (*env)->GetStringUTFChars(env, localeIdJava, NULL);
|
|
|
|
|
|
|
|
// Some devices return with it enclosed in []'s so check if both exists before
|
|
|
|
// removing to ensure it is formatted correctly
|
|
|
|
if (localeListOrig[0] == '[' && localeListOrig[strlen(localeListOrig) - 1] == ']') {
|
|
|
|
localeList = strdup(localeListOrig + 1);
|
|
|
|
localeList[strlen(localeList) - 1] = '\0';
|
|
|
|
} else {
|
|
|
|
localeList = strdup(localeListOrig);
|
|
|
|
}
|
2024-08-07 14:26:16 +00:00
|
|
|
|
2024-08-20 17:19:59 +00:00
|
|
|
// NOTE: This is an IETF BCP 47 language tag and may not correspond exactly tocorrespond ll-CC format
|
|
|
|
// e.g. gsw-u-sd-chzh is a valid BCP 47 language tag, but uses an ISO 639-3 subtag to classify the language.
|
|
|
|
// There is no easy fix to this, as we use ISO 639-2 subtags internally.
|
|
|
|
for (int i = 0; localeList[i]; i++) {
|
|
|
|
if (localeList[i] == '-') {
|
|
|
|
localeList[i] = '_';
|
2024-08-07 14:26:16 +00:00
|
|
|
}
|
|
|
|
}
|
2024-08-20 17:19:59 +00:00
|
|
|
|
|
|
|
(*env)->ReleaseStringUTFChars(env, localeListJava, localeListOrig);
|
2024-08-07 14:26:16 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
jclass timezoneCls = (*env)->FindClass(env, "java/util/TimeZone");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, timezoneCls, "Ljava/util/TimeZone;");
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID timezoneDefaultMethod = (*env)->GetStaticMethodID(env, timezoneCls, "getDefault", "()Ljava/util/TimeZone;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, timezoneDefaultMethod);
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID timezoneIdMethod = (*env)->GetMethodID(env, timezoneCls, "getID", "()Ljava/lang/String;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, timezoneIdMethod);
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
jobject timezoneObj = (*env)->CallStaticObjectMethod(env, timezoneCls, timezoneDefaultMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, timezoneObj);
|
2024-02-01 15:32:07 +00:00
|
|
|
jstring timezoneIdJava = (*env)->CallObjectMethod(env, timezoneObj, timezoneIdMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, timezoneIdJava);
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
const char *timezoneId = (*env)->GetStringUTFChars(env, timezoneIdJava, NULL);
|
|
|
|
|
2024-08-07 14:26:16 +00:00
|
|
|
char *localeListValue = "";
|
|
|
|
if (localeList) {
|
|
|
|
localeListValue = localeList;
|
|
|
|
}
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
// initialize process with these options
|
|
|
|
char *argv[] = {
|
|
|
|
arg0,
|
|
|
|
"-Locale", localeId,
|
|
|
|
"-Local Time Zone", (char *)timezoneId,
|
2024-08-07 14:26:16 +00:00
|
|
|
"-GSAndroidLocaleList", localeListValue,
|
2024-02-01 15:32:07 +00:00
|
|
|
"-GSLogSyslog", "YES" // use syslog (available via logcat) instead of stdout/stderr (not available on Android)
|
|
|
|
};
|
|
|
|
|
|
|
|
GSInitializeProcessAndroidWithArgs(env, context, sizeof(argv)/sizeof(char *), argv, NULL);
|
|
|
|
|
|
|
|
free(arg0);
|
2024-08-07 14:26:16 +00:00
|
|
|
free(localeId);
|
|
|
|
free(localeList);
|
2019-09-25 10:11:50 +00:00
|
|
|
(*env)->ReleaseStringUTFChars(env, packageCodePathJava, packageCodePath);
|
|
|
|
(*env)->ReleaseStringUTFChars(env, packageNameJava, packageName);
|
2024-08-07 14:26:16 +00:00
|
|
|
(*env)->ReleaseStringUTFChars(env, localeIdJava, localeIdOrig);
|
2024-02-01 15:32:07 +00:00
|
|
|
(*env)->ReleaseStringUTFChars(env, timezoneIdJava, timezoneId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
GSInitializeProcessAndroidWithArgs(JNIEnv *env, jobject context, int argc, char **argv, char **envp)
|
|
|
|
{
|
|
|
|
[NSProcessInfo class];
|
|
|
|
|
|
|
|
// create global reference to to prevent garbage collection
|
|
|
|
_androidContext = (*env)->NewGlobalRef(env, context);
|
2019-09-25 10:11:50 +00:00
|
|
|
|
|
|
|
// initialize process
|
|
|
|
[procLock lock];
|
|
|
|
fallbackInitialisation = YES;
|
2024-02-01 15:32:07 +00:00
|
|
|
_gnu_process_args(argc, argv, NULL);
|
2019-09-25 10:11:50 +00:00
|
|
|
[procLock unlock];
|
|
|
|
|
2024-02-01 15:32:07 +00:00
|
|
|
jclass contextCls = (*env)->GetObjectClass(env, context);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, contextCls, "L/android/content/Context;");
|
2019-09-25 10:11:50 +00:00
|
|
|
|
2019-11-05 12:37:59 +00:00
|
|
|
// get File class and path method
|
|
|
|
jclass fileCls = (*env)->FindClass(env, "java/io/File");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CLS_CHECK(env, fileCls, "Ljava/io/File;");
|
2019-11-05 12:37:59 +00:00
|
|
|
jmethodID getAbsolutePathMethod = (*env)->GetMethodID(env, fileCls, "getAbsolutePath", "()Ljava/lang/String;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, getAbsolutePathMethod);
|
2019-11-05 12:37:59 +00:00
|
|
|
|
2019-09-25 10:11:50 +00:00
|
|
|
// get Android files dir
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID filesDirMethod = (*env)->GetMethodID(env, contextCls, "getFilesDir", "()Ljava/io/File;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, filesDirMethod);
|
2019-09-25 10:11:50 +00:00
|
|
|
jobject filesDirObj = (*env)->CallObjectMethod(env, context, filesDirMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, filesDirObj);
|
2019-11-05 12:37:59 +00:00
|
|
|
jstring filesDirJava = (*env)->CallObjectMethod(env, filesDirObj, getAbsolutePathMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, filesDirJava);
|
2024-02-01 15:32:07 +00:00
|
|
|
_androidFilesDir = _NSStringFromJString(env, filesDirJava);
|
2019-11-05 12:37:59 +00:00
|
|
|
|
|
|
|
// get Android cache dir
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID cacheDirMethod = (*env)->GetMethodID(env, contextCls, "getCacheDir", "()Ljava/io/File;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, cacheDirMethod);
|
2019-11-05 12:37:59 +00:00
|
|
|
jobject cacheDirObj = (*env)->CallObjectMethod(env, context, cacheDirMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, cacheDirObj);
|
2019-11-05 12:37:59 +00:00
|
|
|
jstring cacheDirJava = (*env)->CallObjectMethod(env, cacheDirObj, getAbsolutePathMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, cacheDirJava);
|
2024-02-01 15:32:07 +00:00
|
|
|
_androidCacheDir = _NSStringFromJString(env, cacheDirJava);
|
2019-09-25 10:11:50 +00:00
|
|
|
|
|
|
|
// get asset manager and initialize NSBundle
|
2024-02-01 15:32:07 +00:00
|
|
|
jmethodID assetManagerMethod = (*env)->GetMethodID(env, contextCls, "getAssets", "()Landroid/content/res/AssetManager;");
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_METH_CHECK(env, assetManagerMethod);
|
2019-09-25 10:11:50 +00:00
|
|
|
jstring assetManagerJava = (*env)->CallObjectMethod(env, context, assetManagerMethod);
|
2024-08-20 17:19:59 +00:00
|
|
|
GS_JNI_CHECK(env, assetManagerJava);
|
2019-09-25 10:11:50 +00:00
|
|
|
[NSBundle setJavaAssetManager:assetManagerJava withJNIEnv:env];
|
2019-11-05 12:37:59 +00:00
|
|
|
|
|
|
|
// clean up our NSTemporaryDirectory() if it exists
|
|
|
|
NSString *tempDirName = [_androidCacheDir stringByAppendingPathComponent: @"tmp"];
|
|
|
|
[[NSFileManager defaultManager] removeItemAtPath:tempDirName error:NULL];
|
2019-09-25 10:11:50 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-02-13 22:38:55 +00:00
|
|
|
@implementation NSProcessInfo (GNUstep)
|
2003-07-17 09:20:27 +00:00
|
|
|
|
2002-02-13 22:38:55 +00:00
|
|
|
+ (void) initializeWithArguments: (char**)argv
|
|
|
|
count: (int)argc
|
|
|
|
environment: (char**)env
|
|
|
|
{
|
2009-10-12 14:38:49 +00:00
|
|
|
GSInitializeProcess(argc, argv, env);
|
2002-02-13 22:38:55 +00:00
|
|
|
}
|
|
|
|
|
2002-05-27 14:03:10 +00:00
|
|
|
- (BOOL) setLogFile: (NSString*)path
|
|
|
|
{
|
|
|
|
extern int _NSLogDescriptor;
|
|
|
|
int desc;
|
|
|
|
|
2016-03-09 13:16:16 +00:00
|
|
|
#if defined(_WIN32)
|
2012-01-03 10:31:41 +00:00
|
|
|
desc = _wopen((wchar_t*)[path fileSystemRepresentation],
|
|
|
|
O_RDWR|O_CREAT|O_APPEND, 0644);
|
2005-11-05 06:22:15 +00:00
|
|
|
#else
|
2002-05-27 14:03:10 +00:00
|
|
|
desc = open([path fileSystemRepresentation], O_RDWR|O_CREAT|O_APPEND, 0644);
|
2005-11-05 06:22:15 +00:00
|
|
|
#endif
|
2002-05-27 14:03:10 +00:00
|
|
|
if (desc >= 0)
|
|
|
|
{
|
|
|
|
if (_NSLogDescriptor >= 0 && _NSLogDescriptor != 2)
|
|
|
|
{
|
|
|
|
close(_NSLogDescriptor);
|
|
|
|
}
|
|
|
|
_NSLogDescriptor = desc;
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
return NO;
|
|
|
|
}
|
2019-09-25 10:11:50 +00:00
|
|
|
|
|
|
|
#ifdef __ANDROID__
|
|
|
|
- (jobject) androidContext
|
|
|
|
{
|
|
|
|
return _androidContext;
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSString *) androidFilesDir
|
|
|
|
{
|
|
|
|
return _androidFilesDir;
|
|
|
|
}
|
2019-11-05 12:37:59 +00:00
|
|
|
|
|
|
|
- (NSString *) androidCacheDir
|
|
|
|
{
|
|
|
|
return _androidCacheDir;
|
|
|
|
}
|
2019-09-25 10:11:50 +00:00
|
|
|
#endif
|
|
|
|
|
2002-02-13 22:38:55 +00:00
|
|
|
@end
|
|
|
|
|
2006-10-20 10:56:27 +00:00
|
|
|
BOOL
|
|
|
|
GSPrivateEnvironmentFlag(const char *name, BOOL def)
|
2005-11-15 13:07:09 +00:00
|
|
|
{
|
|
|
|
const char *c = getenv(name);
|
|
|
|
BOOL a = def;
|
|
|
|
|
|
|
|
if (c != 0)
|
|
|
|
{
|
|
|
|
a = NO;
|
|
|
|
if ((c[0] == 'y' || c[0] == 'Y') && (c[1] == 'e' || c[1] == 'E')
|
|
|
|
&& (c[2] == 's' || c[2] == 'S') && c[3] == 0)
|
|
|
|
{
|
|
|
|
a = YES;
|
|
|
|
}
|
|
|
|
else if ((c[0] == 't' || c[0] == 'T') && (c[1] == 'r' || c[1] == 'R')
|
|
|
|
&& (c[2] == 'u' || c[2] == 'U') && (c[3] == 'e' || c[3] == 'E')
|
|
|
|
&& c[4] == 0)
|
|
|
|
{
|
|
|
|
a = YES;
|
|
|
|
}
|
|
|
|
else if (isdigit(c[0]) && c[0] != '0')
|
|
|
|
{
|
|
|
|
a = YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2006-10-20 10:56:27 +00:00
|
|
|
const char*
|
|
|
|
GSPrivateArgZero()
|
2002-04-16 15:09:00 +00:00
|
|
|
{
|
|
|
|
if (_gnu_arg_zero == 0)
|
|
|
|
return "";
|
|
|
|
else
|
|
|
|
return _gnu_arg_zero;
|
|
|
|
}
|
|
|
|
|