/*
Реализация среды исполнения языка программирования
Объектно-ориентированный продвинутый векторный транслятор
Copyright © 2021, 2024, 2026 Малик Разработчик
Это свободная программа: вы можете перераспространять ее и/или изменять
ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
в каком она была опубликована Фондом свободного программного обеспечения;
либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.
Эта программа распространяется в надежде, что она будет полезной,
но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
общественной лицензии GNU.
Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
вместе с этой программой. Если это не так, см.
<https://www.gnu.org/licenses/>.
*/
package platform.independent.osservices;
import avt.io.*;
import platform.dependent.*;
import platform.independent.filesystem.*;
public class Process(Object)
{
public static final int MIN_PRIORITY = 1;
public static final int LOW_PRIORITY = 3;
public static final int NORM_PRIORITY = 5;
public static final int HIGH_PRIORITY = 7;
public static final int MAX_PRIORITY = 9;
public static final int STILL_ACTIVE = 259;
public static boolean hasInstance() { return PlatformServices.getInstance().isCurrentProcessHasInstance(); }
public static ByteStream createPipe() { return PlatformServices.getInstance().newPipe(); }
public static Process current() { return PlatformServices.getInstance().getCurrentProcess(); }
protected int fldPriority;
protected String[] fldCommandLine;
protected String fldWorkingDirectory;
private boolean fldStarting;
private long2 fldProcessDs;
private ByteReader fldStandardInput;
private ByteWriter fldStandardOutput;
private ByteWriter fldStandardError;
private final Environment fldEnvironment;
public () {
Process current = Process.current();
Environment environment = createEnvironment();
if(environment == null) environment = new Environment();
fldPriority = NORM_PRIORITY;
fldEnvironment = environment;
if(current == null) return;
environment.assign(current.fldEnvironment);
fldWorkingDirectory = current.fldWorkingDirectory;
fldStandardInput = current.fldStandardInput;
fldStandardOutput = current.fldStandardOutput;
fldStandardError = current.fldStandardError;
}
public void start() throws DirectoryNotFoundException, FileNotFoundException, IOException {
if(isStarting())
{
throw new IllegalProcessStateException(package.getResourceString("illegal-state.process"));
}
try
{
long2 procDs = fldProcessDs;
PlatformServices services = PlatformServices.getInstance();
if(procDs != 0 && !services.isProcessTerminated(procDs))
{
throw new IllegalProcessStateException(package.getResourceString("illegal-state.process.already-started"));
}
String[] procArg = getCommandLine();
if(procArg == null || procArg.length <= 0)
{
throw new IllegalProcessStateException(package.getResourceString("illegal-state.process.command-line"));
}
char[][] procEnv;
with(fldEnvironment)
{
Mutex operation = operation;
operation.lock();
try
{
EnvironmentTable variables = variables;
int length = variables.length;
procEnv = new char[length][];
for(int index = 0; index < length; index++)
{
String name = variables[index];
String value = variables[name];
int nlength = name.length;
int vlength = value.length;
char[] component = new char[nlength + vlength + 1];
name.getChars(0, nlength, component, 0);
value.getChars(0, vlength, component, nlength + 1);
component[nlength] = '=';
procEnv[index] = component;
}
} finally
{
operation.unlock();
}
}
ProcessParameters procPrm = new ProcessParameters() {
priority = fldPriority,
environment = procEnv,
arguments = procArg,
workingDirectory = fldWorkingDirectory,
standardInput = fldStandardInput,
standardOutput = fldStandardOutput,
standardError = fldStandardError
};
fldProcessDs = services.startProcess(procPrm);
if(procDs != 0) services.closeProcessDescriptor(procDs);
} finally
{
clearStarting();
}
}
public void join(long timeInMillis, int timeInNanos) {
long2 procDs = fldProcessDs;
if(procDs == 0)
{
throw new IllegalProcessStateException(package.getResourceString("illegal-state.process"));
}
if(timeInMillis < 0)
{
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.negative"), new Object[] { "timeInMillis" }));
}
if(timeInNanos < 0 || timeInNanos > 999999)
{
throw new IllegalArgumentException(String.format(avt.lang.package.getResourceString("illegal-argument.out-of-range"), new Object[] { "timeInNanos" }));
}
PlatformServices.getInstance().joinProcess(procDs, timeInMillis, timeInNanos);
}
public boolean isTerminated() {
long2 procDs = fldProcessDs;
return procDs != 0 && PlatformServices.getInstance().isProcessTerminated(procDs);
}
public int getExitCode() {
long2 procDs = fldProcessDs;
return procDs == 0 ? 0 : PlatformServices.getInstance().getProcessExitCode(procDs);
}
public final void join(long timeInMillis) { join(timeInMillis, 0); }
public final void join() { join(0, 0); }
public final int priority { read = getPriority, write = setPriority }
public final String[] commandLine { read = getCommandLine, write = setCommandLine }
public final String workingDirectory { read = getWorkingDirectory, write = setWorkingDirectory }
public final Environment environment { read = fldEnvironment, write = setEnvironment }
public final ByteReader standardInput { read = fldStandardInput, write = setStandardInput }
public final ByteWriter standardOutput { read = fldStandardOutput, write = setStandardOutput }
public final ByteWriter standardError { read = fldStandardError, write = setStandardError }
protected void beforeDestruction() {
long2 procDs = fldProcessDs;
if(procDs != 0) PlatformServices.getInstance().closeProcessDescriptor(procDs);
}
protected void setPriority(int newPriority) {
if(newPriority < MIN_PRIORITY) newPriority = MIN_PRIORITY;
if(newPriority > MAX_PRIORITY) newPriority = MAX_PRIORITY;
fldPriority = newPriority;
}
protected void setCommandLine(String[] newCommandLine) {
if(newCommandLine == null)
{
fldCommandLine = null;
return;
}
int length = newCommandLine.length;
String[] locCommandLine = new String[length];
for(int index = 0; index < length; index++)
{
String component = newCommandLine[index];
if(component == null || component.indexOf(0) >= 0 || component.indexOf('\"') >= 0)
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "commandLine" }));
}
if(index == 0 && !PlatformServices.getInstance().isInternalPathFull(component))
{
throw new IllegalPropertyValueException(package.getResourceString("illegal-property.process.command-line"));
}
locCommandLine[index] = component;
}
locCommandLine.finalize();
fldCommandLine = locCommandLine;
}
protected void setWorkingDirectory(String newWorkingDirectory) {
if(newWorkingDirectory == null)
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "workingDirectory" }));
}
fldWorkingDirectory = newWorkingDirectory;
}
protected void setEnvironment(Environment newEnvironment) {
if(newEnvironment == null)
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "environment" }));
}
fldEnvironment.assign(newEnvironment);
}
protected void setStandardInput(ByteReader newStandardInput) {
if(newStandardInput != null && !PlatformServices.getInstance().isPlatformInputStream(newStandardInput))
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardInput" }));
}
fldStandardInput = newStandardInput;
}
protected void setStandardOutput(ByteWriter newStandardOutput) {
if(newStandardOutput != null && !PlatformServices.getInstance().isPlatformOutputStream(newStandardOutput))
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardOutput" }));
}
fldStandardOutput = newStandardOutput;
}
protected void setStandardError(ByteWriter newStandardError) {
if(newStandardError != null && !PlatformServices.getInstance().isPlatformOutputStream(newStandardError))
{
throw new IllegalPropertyValueException(String.format(avt.lang.package.getResourceString("illegal-property"), new Object[] { "standardError" }));
}
fldStandardError = newStandardError;
}
protected int getPriority() { return fldPriority; }
protected String getWorkingDirectory() { return fldWorkingDirectory; }
protected Environment createEnvironment() { return null; }
protected final void clearStarting() { fldStarting = false; }
protected final native boolean isStarting();
private String[] getCommandLine() {
String[] result = fldCommandLine;
if(result != null && result.isMutable())
{
int length = result.length;
Array.copy(result, 0, fldCommandLine = result = new String[length], 0, length);
result.finalize();
}
return result;
}
}