PLUGIN sys lang: "C++" version: "1.0" date: "2023-03-20" author: "Julien BRUGUIER" maintainer: "Julien BRUGUIER " synopsis: "An implementation of operating system access for SVM." description: %{ This plugin enables basic access to the operating system in which the SVM is running. %} example: "Hello system!" %{ .nf #!===SVMBIN=== LOG PLUGIN "svmcom.so" PLUGIN "===PLUGINLIB===" PROCESS "test" CODE "main" INLINE :memory (STR*2,INT)/sys :sys.name -> (sys/0) :sys.user -> (sys/1) :sys.cpu -> (sys/2) :com.message "OS: " @(sys/0) " used by " @(sys/1) " with " @(sys/2) " CPUs." END END .fi %} includes: %{ #include #include #include #include #include %} code: %{ static const int USER_NAME_MAX = 128; %} DEFINE SYSTEM INSTRUCTION sys.name -> STR ? %{ char name[HOST_NAME_MAX]; if(::gethostname(name,HOST_NAME_MAX)) { return NEW_NULL_VALUE(string); } return NEW_VALUE(string,::svm_string_new__raw(svm,name)); %} help: %{ This instruction returns the system host name. When the host name can not be retrieved, a null string is returned. %} SYSTEM INSTRUCTION sys.user -> STR ? %{ char name[USER_NAME_MAX+1]; if(::getlogin_r(name,USER_NAME_MAX)) { return NEW_NULL_VALUE(string); } return NEW_VALUE(string,::svm_string_new__raw(svm,name)); %} help: %{ This instruction returns the login user name. When the user name can not be retrieved, a null string is returned. %} SYSTEM INSTRUCTION sys.cpu -> INT %{ auto cpu = std::thread::hardware_concurrency(); return NEW_VALUE(integer,cpu); %} help: %{ This instruction returns the number of processor cores available on the system. .P This value can be useful to auto-tune schedulers to adapt to every system. %} INSTRUCTION sys.getenv STR -> STR ? %{ auto name = ARGV_VALUE(0,string); char *value = ::getenv(name.string); if(not value) { return NEW_NULL_VALUE(string); } return NEW_VALUE(string,::svm_string_new__raw(svm,value)); %} help: %{ This instruction returns the eventual value of an environment variable. When the variable does not exist, a nul string is returned. .P The instruction raises a FAILURE interruption when the variable name is ill-formed. %} SYSTEM INSTRUCTION sys.setenv STR STR ? %{ auto name = ARGV_VALUE(0,string); if(argc==1) { if(::unsetenv(name.string)) { ERROR_INTERNAL(FAILURE,"Invalid variable name"); } RETURN; } auto value = ARGV_VALUE(1,string); if(::setenv(name.string,value.string,1/*overwrite*/)) { ERROR_INTERNAL(FAILURE,"Invalid variable name"); } %} help: %{ This instruction changes the eventual value of an environment variable. When the second parameter is not provided, the variable is deleted. Otherwise, the variable is created or updated with the new value. .P The instruction raises a FAILURE interruption when the variable name is ill-formed. %} INSTRUCTION sys.listenv -> PTR %{ std::map variables; for(char **v=environ ; *v ; ++v) { auto s = std::string(*v); auto equal = s.find('='); variables.insert(std::make_pair(s.substr(0,equal),s.substr(equal+1))); } SVM_Memory_Zone z = ::svm_memory_zone_new(svm); ::svm_memory_zone_append_internal__raw(svm,z,POINTER,variables.size()); SVM_Value_Pointer v = ::svm_memory_allocate(svm,CURRENT(kernel),z); SVM_Memory_Zone zz = ::svm_memory_zone_new(svm); ::svm_memory_zone_append_internal__raw(svm,zz,STRING,2); SVM_Address a = ::svm_value_pointer_get_address(svm,v); for(const auto& vv: variables) { SVM_Value_Pointer rv = ::svm_memory_allocate(svm,CURRENT(kernel),zz); SVM_Value_String *av =::svm_value_array_new(svm,2); av[0] = NEW_VALUE(string,NEW_STRING(vv.first)); av[1] = NEW_VALUE(string,NEW_STRING(vv.second)); ::svm_value_state_set_movable(svm,av[0]); ::svm_value_state_set_movable(svm,av[1]); ::svm_memory_write_pointer(svm,CURRENT(kernel),rv,av); VARIABLE_DELETE(av); ::svm_value_state_set_movable(svm,rv); ::svm_memory_write_address(svm,CURRENT(kernel),a++,rv); } return v; %} help: %{ This instruction returns all defined environment variables. It returns a pointer to an array of pointers. Each element pointer indicates two strings: the first one is the variable name, and the second one the variable value. %}