feat(#3251): getenv + getpid via syscalls

This commit is contained in:
maxonfjvipon 2024-08-15 12:21:29 +03:00
parent 590bd7dc4a
commit 2265048b2c
No known key found for this signature in database
GPG Key ID: D8563899D473D273
9 changed files with 285 additions and 24 deletions

View File

@ -20,6 +20,9 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+alias org.eolang.sys.os
+alias org.eolang.sys.posix
+alias org.eolang.sys.win32
+architect yegor256@gmail.com
+home https://github.com/objectionary/eo
+package org.eolang.sys
@ -31,4 +34,13 @@
# If return `string` is empty - the variable does not exist.
#
# See https://man7.org/linux/man-pages/man3/getenv.3.html
[name] > getenv /string
[name] > getenv
output. > @
if.
os.is-windows
win32
"GetEnvironmentVariable"
* name 512
posix
"getenv"
* name

View File

@ -27,6 +27,7 @@
*/
package EOorg.EOeolang.EOsys; // NOPMD
import EOorg.EOeolang.EOsys.Posix.GetenvSyscall;
import EOorg.EOeolang.EOsys.Posix.GetpidSyscall;
import EOorg.EOeolang.EOsys.Posix.ReadSyscall;
import EOorg.EOeolang.EOsys.Posix.WriteSyscall;
@ -59,6 +60,7 @@ public final class EOposix$EOφ extends PhDefault implements Atom {
EOposix$EOφ.SYS_CALLS.put("getpid", GetpidSyscall::new);
EOposix$EOφ.SYS_CALLS.put("read", ReadSyscall::new);
EOposix$EOφ.SYS_CALLS.put("write", WriteSyscall::new);
EOposix$EOφ.SYS_CALLS.put("getenv", GetenvSyscall::new);
}
@Override

View File

@ -27,6 +27,8 @@
*/
package EOorg.EOeolang.EOsys; // NOPMD
import EOorg.EOeolang.EOsys.Win32.GetCurrentProcessIdFuncCall;
import EOorg.EOeolang.EOsys.Win32.GetEnvironmentVariableFuncCall;
import EOorg.EOeolang.EOsys.Win32.ReadFileFuncCall;
import EOorg.EOeolang.EOsys.Win32.WriteFileFuncCall;
import java.util.HashMap;
@ -55,8 +57,10 @@ public final class EOwin32$EOφ extends PhDefault implements Atom {
static final Map<String, Function<Phi, Syscall>> FUNCTIONS = new HashMap<>();
static {
EOwin32$EOφ.FUNCTIONS.put("WriteFile", WriteFileFuncCall::new);
EOwin32$EOφ.FUNCTIONS.put("GetCurrentProcessId", GetCurrentProcessIdFuncCall::new);
EOwin32$EOφ.FUNCTIONS.put("ReadFile", ReadFileFuncCall::new);
EOwin32$EOφ.FUNCTIONS.put("WriteFile", WriteFileFuncCall::new);
EOwin32$EOφ.FUNCTIONS.put("GetEnvironmentVariable", GetEnvironmentVariableFuncCall::new);
}
@Override

View File

@ -115,4 +115,11 @@ public interface CStdLib extends Library {
* @return Number of bytes was read.
*/
int read(int descriptor, byte[] buf, int size);
/**
* Get environment variable.
* @param name Name of the variable
* @return Name of the environment variable
*/
String getenv(String name);
}

View File

@ -21,47 +21,46 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
* @checkstyle TrailingCommentCheck (3 lines)
*/
package EOorg.EOeolang.EOsys; // NOPMD
package EOorg.EOeolang.EOsys.Posix; // NOPMD
import org.eolang.AtVoid;
import org.eolang.Atom;
import EOorg.EOeolang.EOsys.Syscall;
import org.eolang.Data;
import org.eolang.Dataized;
import org.eolang.PhDefault;
import org.eolang.Phi;
import org.eolang.XmirObject;
/**
* Getenv.
* Getenv syscall.
* @since 0.40
* @checkstyle TypeNameCheck (5 lines)
*/
@XmirObject(oname = "getenv")
public final class EOgetenv extends PhDefault implements Atom {
public final class GetenvSyscall implements Syscall {
/**
* Posix object.
*/
private final Phi posix;
/**
* Ctor.
* @param posix Posix object
*/
@SuppressWarnings("PMD.ConstructorOnlyInitializesOrCallOtherConstructors")
public EOgetenv() {
this.add("name", new AtVoid("name"));
public GetenvSyscall(final Phi posix) {
this.posix = posix;
}
@Override
public Phi lambda() throws Exception {
final String env = System.getenv(
new Dataized(this.take("name")).asString()
);
final Phi var;
if (env != null) {
var = new Data.ToPhi(env);
public Phi make(final Phi... params) {
final Phi result = this.posix.take("return").copy();
final String env = CStdLib.INSTANCE.getenv(new Dataized(params[0]).asString());
final boolean present = env != null;
result.put(0, new Data.ToPhi(present));
if (present) {
result.put(1, new Data.ToPhi(env));
} else {
var = new Data.ToPhi("");
result.put(1, new Data.ToPhi(""));
}
return var;
return result;
}
}

View File

@ -0,0 +1,62 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2024 Objectionary.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
* @checkstyle TrailingCommentCheck (3 lines)
*/
package EOorg.EOeolang.EOsys.Win32; // NOPMD
import EOorg.EOeolang.EOsys.Syscall;
import org.eolang.Data;
import org.eolang.PhDefault;
import org.eolang.Phi;
/**
* GetCurrentProcessId kernel32 function call.
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocessid">here for details</a>
* @since 0.40.0
*/
public final class GetCurrentProcessIdFuncCall implements Syscall {
/**
* Win32 object.
*/
private final Phi win;
/**
* Ctor.
* @param win Win32 object
*/
public GetCurrentProcessIdFuncCall(final Phi win) {
this.win = win;
}
@Override
public Phi make(final Phi... params) {
final Phi result = this.win.take("return").copy();
result.put(0, new Data.ToPhi(Kernel32.INSTANCE.GetCurrentProcessId()));
result.put(1, new PhDefault());
return result;
}
}

View File

@ -0,0 +1,72 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2024 Objectionary.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
* @checkstyle TrailingCommentCheck (3 lines)
*/
package EOorg.EOeolang.EOsys.Win32; // NOPMD
import EOorg.EOeolang.EOsys.Syscall;
import java.util.Arrays;
import org.eolang.Data;
import org.eolang.Dataized;
import org.eolang.Phi;
/**
* GetEnvironmentVariable kernel32 function call.
* @see <a href="https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-getenvironmentvariable">here for details</a>
* @since 0.40.0
*/
public final class GetEnvironmentVariableFuncCall implements Syscall {
/**
* Win32 object.
*/
private final Phi win;
/**
* Ctor.
* @param win Win32 object
*/
public GetEnvironmentVariableFuncCall(final Phi win) {
this.win = win;
}
@Override
public Phi make(final Phi... params) {
final int size = new Dataized(params[1]).asNumber().intValue();
final char[] buf = new char[size];
final int length = Kernel32.INSTANCE.GetEnvironmentVariable(
new Dataized(params[0]).asString(), buf, size
);
final Phi result = this.win.take("return").copy();
result.put(0, new Data.ToPhi(length));
if (length > 0) {
result.put(1, new Data.ToPhi(new String(Arrays.copyOf(buf, length))));
} else {
result.put(1, new Data.ToPhi(""));
}
return result;
}
}

View File

@ -163,4 +163,33 @@ public interface Kernel32 extends StdCallLibrary, WinNT, Wincon {
int flags,
HANDLE template
);
/**
* Retrieves the contents of the specified variable from the environment
* block of the calling process.
* @param name The name of the environment variable.
* @param buffer A pointer to a buffer that receives the contents of the
* specified environment variable as a null-terminated string. An
* environment variable has a maximum size limit of 32,767
* characters, including the null-terminating character.
* @param size The size of the buffer pointed to by the buffer parameter,
* including the null-terminating character, in characters.
* @return If the function succeeds, the return value is the number of
* characters stored in the buffer pointed to by buffer, not
* including the terminating null character. If buffer is not
* large enough to hold the data, the return value is the buffer
* size, in characters, required to hold the string and its
* terminating null character and the contents of buffer are
* undefined. If the function fails, the return value is zero. To
* get extended error information, call GetLastError.
* @checkstyle MethodNameCheck (5 lines)
*/
int GetEnvironmentVariable(String name, char[] buffer, int size);
/**
* This function returns the process identifier of the calling process.
* @return The return value is the process identifier of the calling process.
* @checkstyle MethodNameCheck (5 lines)
*/
int GetCurrentProcessId();
}

View File

@ -0,0 +1,74 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2024 Objectionary.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
* @checkstyle TrailingCommentCheck (3 lines)
*/
package EOorg.EOeolang.EOsys; // NOPMD
import EOorg.EOeolang.EOtuple$EOempty;
import java.lang.management.ManagementFactory;
import org.eolang.Data;
import org.eolang.Dataized;
import org.eolang.PhWith;
import org.eolang.Phi;
import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.OS;
/**
* Test case for {@link EOwin32}.
*
* @since 0.40
* @checkstyle TypeNameCheck (100 lines)
*/
@SuppressWarnings("JTCOP.RuleAllTestsHaveProductionClass")
final class EOwin32Test {
@Test
@DisabledOnOs({OS.LINUX, OS.MAC, OS.AIX})
void invokesGetCurrentProcessIdCorrectly() {
MatcherAssert.assertThat(
"The \"GetCurrentProcessId\" function call was expected to work correctly",
new Dataized(
new PhWith(
new PhWith(
Phi.Φ.take("org.eolang.sys.win32").copy(),
"name",
new Data.ToPhi("GetCurrentProcessId")
),
"args",
new EOtuple$EOempty()
).take("code")
).take(Long.class),
Matchers.equalTo(
Long.parseLong(
ManagementFactory.getRuntimeMXBean()
.getName().split("@")[0]
)
)
);
}
}