rust/src/rt/rust_builtin.c

472 lines
9.3 KiB
C
Raw Normal View History

2015-01-29 08:19:28 +01:00
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2012-12-10 15:44:02 -08:00
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#if !defined(_WIN32)
2013-12-23 21:01:57 -08:00
#include <stdint.h>
2012-04-03 10:32:26 -07:00
#include <time.h>
2013-12-23 21:01:57 -08:00
#include <string.h>
#include <assert.h>
#include <stdlib.h>
2013-12-23 21:01:57 -08:00
#include <dirent.h>
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
#include <pthread.h>
2013-12-23 21:01:57 -08:00
#include <signal.h>
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
2013-12-23 21:01:57 -08:00
#include <unistd.h>
2013-12-23 21:01:57 -08:00
#ifdef __APPLE__
#include <TargetConditionals.h>
#include <mach/mach_time.h>
#if !(TARGET_OS_IPHONE)
#include <crt_externs.h>
#endif
2012-02-09 14:08:24 +08:00
#endif
char*
rust_list_dir_val(struct dirent* entry_ptr) {
return entry_ptr->d_name;
}
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
// Android's struct dirent does have d_type from the very beginning
// (android-3). _DIRENT_HAVE_D_TYPE is not defined all the way to android-21
// though...
#if defined(__ANDROID__)
# define _DIRENT_HAVE_D_TYPE
#endif
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
int
rust_dir_get_mode(struct dirent* entry_ptr) {
#if defined(_DIRENT_HAVE_D_TYPE) || defined(__APPLE__)
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
switch (entry_ptr->d_type) {
case DT_BLK: return S_IFBLK;
case DT_CHR: return S_IFCHR;
case DT_FIFO: return S_IFIFO;
case DT_LNK: return S_IFLNK;
case DT_REG: return S_IFREG;
case DT_SOCK: return S_IFSOCK;
case DT_DIR: return S_IFDIR;
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
}
#endif
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
return -1;
}
std: Expand the area of std::fs This commit is an implementation of [RFC 1044][rfc] which adds additional surface area to the `std::fs` module. All new APIs are `#[unstable]` behind assorted feature names for each one. [rfc]: https://github.com/rust-lang/rfcs/pull/1044 The new APIs added are: * `fs::canonicalize` - bindings to `realpath` on unix and `GetFinalPathNameByHandle` on windows. * `fs::symlink_metadata` - similar to `lstat` on unix * `fs::FileType` and accessor methods as `is_{file,dir,symlink}` * `fs::Metadata::file_type` - accessor for the raw file type * `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows but requires a syscall on unix. * `fs::DirEntry::file_type` - access the file type which may not require a syscall on most platforms. * `fs::DirEntry::file_name` - access just the file name without leading components. * `fs::PathExt::symlink_metadata` - convenience method for the top-level function. * `fs::PathExt::canonicalize` - convenience method for the top-level function. * `fs::PathExt::read_link` - convenience method for the top-level function. * `fs::PathExt::read_dir` - convenience method for the top-level function. * `std::os::raw` - type definitions for raw OS/C types available on all platforms. * `std::os::$platform` - new modules have been added for all currently supported platforms (e.g. those more specific than just `unix`). * `std::os::$platform::raw` - platform-specific type definitions. These modules are populated with the bare essentials necessary for lowing I/O types into their raw representations, and currently largely consist of the `stat` definition for unix platforms. This commit also deprecates `Metadata::{modified, accessed}` in favor of inspecting the raw representations via the lowering methods of `Metadata`.
2015-04-15 23:21:13 -07:00
ino_t
rust_dir_get_ino(struct dirent* entry_ptr) {
return entry_ptr->d_ino;
}
DIR*
rust_opendir(char *dirname) {
return opendir(dirname);
}
int
rust_readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) {
return readdir_r(dirp, entry, result);
}
int
rust_dirent_t_size() {
return sizeof(struct dirent);
}
2013-08-09 22:21:01 -07:00
#if defined(__BSD__)
static int
2013-08-09 22:21:01 -07:00
get_num_cpus() {
/* swiped from http://stackoverflow.com/questions/150355/
programmatically-find-the-number-of-cores-on-a-machine */
unsigned int numCPU;
int mib[4];
size_t len = sizeof(numCPU);
/* set the mib for hw.ncpu */
mib[0] = CTL_HW;
mib[1] = HW_AVAILCPU; // alternatively, try HW_NCPU;
/* get the number of CPUs from the system */
sysctl(mib, 2, &numCPU, &len, NULL, 0);
if( numCPU < 1 ) {
mib[1] = HW_NCPU;
sysctl( mib, 2, &numCPU, &len, NULL, 0 );
if( numCPU < 1 ) {
numCPU = 1;
}
}
return numCPU;
}
#elif defined(__GNUC__)
static int
2013-08-09 22:21:01 -07:00
get_num_cpus() {
return sysconf(_SC_NPROCESSORS_ONLN);
}
#endif
2013-06-05 22:34:35 -07:00
uintptr_t
2013-06-05 22:34:35 -07:00
rust_get_num_cpus() {
return get_num_cpus();
}
#if defined(__DragonFly__)
#include <errno.h>
// In DragonFly __error() is an inline function and as such
// no symbol exists for it.
int *__dfly_error(void) { return __error(); }
#endif
2015-01-16 23:51:04 -08:00
#if defined(__Bitrig__)
#include <stdio.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <limits.h>
int rust_get_path(void *p, size_t* sz)
{
int mib[4];
char *eq = NULL;
char *key = NULL;
char *val = NULL;
char **menv = NULL;
size_t maxlen, len;
int nenv = 0;
int i;
if ((p == NULL) && (sz == NULL))
return -1;
/* get the argv array */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = getpid();
mib[3] = KERN_PROC_ENV;
/* get the number of bytes needed to get the env */
maxlen = 0;
if (sysctl(mib, 4, NULL, &maxlen, NULL, 0) == -1)
return -1;
/* allocate the buffer */
if ((menv = calloc(maxlen, sizeof(char))) == NULL)
return -1;
/* get the env array */
if (sysctl(mib, 4, menv, &maxlen, NULL, 0) == -1)
{
free(menv);
return -1;
}
mib[3] = KERN_PROC_NENV;
len = sizeof(int);
/* get the length of env array */
if (sysctl(mib, 4, &nenv, &len, NULL, 0) == -1)
{
free(menv);
return -1;
}
/* find _ key and resolve the value */
for (i = 0; i < nenv; i++)
{
if ((eq = strstr(menv[i], "=")) == NULL)
continue;
key = menv[i];
val = eq + 1;
*eq = '\0';
if (strncmp(key, "PATH", maxlen) != 0)
continue;
if (p == NULL)
{
/* return the length of the value + NUL */
*sz = strnlen(val, maxlen) + 1;
free(menv);
return 0;
}
else
{
/* copy *sz bytes to the output buffer */
memcpy(p, val, *sz);
free(menv);
return 0;
}
}
free(menv);
return -1;
}
int rust_get_path_array(void * p, size_t * sz)
{
char *path, *str;
char **buf;
int i, num;
size_t len;
if ((p == NULL) && (sz == NULL))
return -1;
/* get the length of the PATH value */
if (rust_get_path(NULL, &len) == -1)
return -1;
if (len == 0)
return -1;
/* allocate the buffer */
if ((path = calloc(len, sizeof(char))) == NULL)
return -1;
/* get the PATH value */
if (rust_get_path(path, &len) == -1)
{
free(path);
return -1;
}
/* count the number of parts in the PATH */
num = 1;
for(str = path; *str != '\0'; str++)
{
if (*str == ':')
num++;
}
/* calculate the size of the buffer for the 2D array */
len = (num * sizeof(char*) + 1) + strlen(path) + 1;
if (p == NULL)
{
free(path);
*sz = len;
return 0;
}
/* make sure we have enough buffer space */
if (*sz < len)
{
free(path);
return -1;
}
/* zero out the buffer */
buf = (char**)p;
memset(buf, 0, *sz);
/* copy the data into the right place */
str = p + ((num+1) * sizeof(char*));
memcpy(str, path, strlen(path));
/* parse the path into it's parts */
for (i = 0; i < num && (buf[i] = strsep(&str, ":")) != NULL; i++) {;}
buf[num] = NULL;
free(path);
return 0;
}
int rust_get_argv_zero(void* p, size_t* sz)
{
int mib[4];
char **argv = NULL;
size_t len;
if ((p == NULL) && (sz == NULL))
return -1;
/* get the argv array */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = getpid();
mib[3] = KERN_PROC_ARGV;
/* request KERN_PROC_ARGV size */
len = 0;
if (sysctl(mib, 4, NULL, &len, NULL, 0) == -1)
return -1;
/* allocate buffer to receive the values */
if ((argv = malloc(len)) == NULL)
return -1;
/* get the argv array */
if (sysctl(mib, 4, argv, &len, NULL, 0) == -1)
{
free(argv);
return -1;
}
/* get length of argv[0] */
len = strnlen(argv[0], len) + 1;
if (p == NULL)
{
*sz = len;
free(argv);
return 0;
}
if (*sz < len)
{
free(argv);
return -1;
}
memset(p, 0, len);
memcpy(p, argv[0], len);
free(argv);
return 0;
}
const char * rust_current_exe()
2015-01-16 23:51:04 -08:00
{
static char *self = NULL;
char *argv0;
char **paths;
size_t sz;
int i;
Reduce the reliance on `PATH_MAX` - Rewrite `std::sys::fs::readlink` not to rely on `PATH_MAX` It currently has the following problems: 1. It uses `_PC_NAME_MAX` to query the maximum length of a file path in the underlying system. However, the meaning of the constant is the maximum length of *a path component*, not a full path. The correct constant should be `_PC_PATH_MAX`. 2. `pathconf` *may* fail if the referred file does not exist. This can be problematic if the file which the symbolic link points to does not exist, but the link itself does exist. In this case, the current implementation resorts to the hard-coded value of `1024`, which is not ideal. 3. There may exist a platform where there is no limit on file path lengths in general. That's the reaon why GNU Hurd doesn't define `PATH_MAX` at all, in addition to having `pathconf` always returning `-1`. In these platforms, the content of the symbolic link can be silently truncated if the length exceeds the hard-coded limit mentioned above. 4. The value obtained by `pathconf` may be outdated at the point of actually calling `readlink`. This is inherently racy. This commit introduces a loop that gradually increases the length of the buffer passed to `readlink`, eliminating the need of `pathconf`. - Remove the arbitrary memory limit of `std::sys::fs::realpath` As per POSIX 2013, `realpath` will return a malloc'ed buffer if the second argument is a null pointer.[1] [1] http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html - Comment on functions that are still using `PATH_MAX` There are some functions that only work in terms of `PATH_MAX`, such as `F_GETPATH` in OS X. Comments on them for posterity.
2015-08-19 13:11:40 +09:00
/* If `PATH_MAX` is defined on the platform, `realpath` will truncate the
* resolved path up to `PATH_MAX`. While this can make the resolution fail if
* the executable is placed in a deep path, the usage of a buffer whose
* length depends on `PATH_MAX` is still memory safe. */
char buf[2*PATH_MAX], exe[PATH_MAX];
2015-01-16 23:51:04 -08:00
if (self != NULL)
return self;
if (rust_get_argv_zero(NULL, &sz) == -1)
return NULL;
if ((argv0 = calloc(sz, sizeof(char))) == NULL)
return NULL;
if (rust_get_argv_zero(argv0, &sz) == -1)
{
free(argv0);
return NULL;
}
/* if argv0 is a relative or absolute path, resolve it with realpath */
if ((*argv0 == '.') || (*argv0 == '/') || (strstr(argv0, "/") != NULL))
{
self = realpath(argv0, NULL);
free(argv0);
return self;
}
/* get the path array */
if (rust_get_path_array(NULL, &sz) == -1)
{
free(argv0);
return NULL;
}
if ((paths = calloc(sz, sizeof(char))) == NULL)
{
free(argv0);
return NULL;
}
if (rust_get_path_array(paths, &sz) == -1)
{
free(argv0);
free(paths);
return NULL;
}
for(i = 0; paths[i] != NULL; i++)
{
snprintf(buf, 2*PATH_MAX, "%s/%s", paths[i], argv0);
if (realpath(buf, exe) == NULL)
continue;
if (access(exe, F_OK | X_OK) == -1)
continue;
self = strdup(exe);
free(argv0);
free(paths);
return self;
}
free(argv0);
free(paths);
return NULL;
}
#elif defined(__OpenBSD__)
2015-01-29 08:19:28 +01:00
#include <sys/param.h>
#include <sys/sysctl.h>
#include <limits.h>
const char * rust_current_exe() {
2015-01-29 08:19:28 +01:00
static char *self = NULL;
if (self == NULL) {
int mib[4];
char **argv = NULL;
size_t argv_len;
/* initialize mib */
mib[0] = CTL_KERN;
mib[1] = KERN_PROC_ARGS;
mib[2] = getpid();
mib[3] = KERN_PROC_ARGV;
/* request KERN_PROC_ARGV size */
argv_len = 0;
if (sysctl(mib, 4, NULL, &argv_len, NULL, 0) == -1)
return (NULL);
/* allocate size */
if ((argv = malloc(argv_len)) == NULL)
return (NULL);
/* request KERN_PROC_ARGV */
if (sysctl(mib, 4, argv, &argv_len, NULL, 0) == -1) {
free(argv);
return (NULL);
}
/* get realpath if possible */
if ((argv[0] != NULL) && ((*argv[0] == '.') || (*argv[0] == '/')
2015-02-05 14:38:56 -08:00
|| (strstr(argv[0], "/") != NULL)))
2015-01-29 08:19:28 +01:00
self = realpath(argv[0], NULL);
else
self = NULL;
/* cleanup */
free(argv);
}
return (self);
}
2015-01-16 23:51:04 -08:00
2015-01-29 08:19:28 +01:00
#endif
#endif // !defined(_WIN32)
2010-06-23 21:03:09 -07:00
//
// Local Variables:
// mode: C++
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// End:
//