diff --git a/flake.nix b/flake.nix index 235d5aa4..c7d7c689 100644 --- a/flake.nix +++ b/flake.nix @@ -116,21 +116,18 @@ { system = "x86_64-linux"; config.allowUnfree = true; - overlays = - [ - inputs.self.overlays.default - (final: prev: - { - boost = (prev.boost.override { zstd = null; }).overrideAttrs (prev: - { patches = prev.patches or [] ++ [ ./local/pkgs/winjob/boost.patch ]; }); - magic-enum = prev.magic-enum.overrideAttrs (prev: { cmakeFlags = prev.cmakeFlags ++ - [ "-DMAGIC_ENUM_OPT_BUILD_EXAMPLES=OFF" "-DMAGIC_ENUM_OPT_BUILD_TESTS=OFF" ]; }); - range-v3 = prev.range-v3.overrideAttrs (prev: { cmakeFlags = prev.cmakeFlags ++ - [ "-DRANGE_V3_DOCS=OFF" "-DRANGE_V3_TESTS=OFF" "-DRANGE_V3_EXAMPLES=OFF" ]; }); - abseil-cpp = prev.abseil-cpp.overrideAttrs (prev: { buildInputs = prev.buildInputs ++ - [ final.windows.pthreads ]; }); - }) - ]; + overlays = [ inputs.self.overlays.default ]; + crossOverlays = [(final: prev: + { + boost = (prev.boost.override { zstd = null; }).overrideAttrs (prev: + { patches = prev.patches or [] ++ [ ./local/pkgs/winjob/boost.patch ]; }); + magic-enum = prev.magic-enum.overrideAttrs (prev: { cmakeFlags = prev.cmakeFlags ++ + [ "-DMAGIC_ENUM_OPT_BUILD_EXAMPLES=OFF" "-DMAGIC_ENUM_OPT_BUILD_TESTS=OFF" ]; }); + range-v3 = prev.range-v3.overrideAttrs (prev: { cmakeFlags = prev.cmakeFlags ++ + [ "-DRANGE_V3_DOCS=OFF" "-DRANGE_V3_TESTS=OFF" "-DRANGE_V3_EXAMPLES=OFF" ]; }); + abseil-cpp = prev.abseil-cpp.overrideAttrs (prev: { buildInputs = prev.buildInputs ++ + [ final.windows.pthreads ]; }); + })]; }; in rec { @@ -213,7 +210,7 @@ winjob = pkgs.mkShell { inputsFrom = [ pkgs.localPackages.winjob ]; - packages = [ pkgs.clang-tools_18 pkgs.qt6.full pkgs.qtcreator ]; + packages = with pkgs; [ clang-tools_18 qt6.full qtcreator ]; CMAKE_EXPORT_COMPILE_COMMANDS = "1"; }; }; diff --git a/local/pkgs/winjob/.clangd b/local/pkgs/winjob/.clangd index 31d7203a..a6585d7e 100644 --- a/local/pkgs/winjob/.clangd +++ b/local/pkgs/winjob/.clangd @@ -1,3 +1,3 @@ CompileFlags: - Add: [ -Wall, -Wextra, -std=c++26 ] + Add: [ -Wall, -Wextra, -std=c++23 ] Compiler: g++ diff --git a/local/pkgs/winjob/CMakeLists.txt b/local/pkgs/winjob/CMakeLists.txt index f083fad3..57b18179 100644 --- a/local/pkgs/winjob/CMakeLists.txt +++ b/local/pkgs/winjob/CMakeLists.txt @@ -15,17 +15,23 @@ set(WINJOB_VERSION "unknown" CACHE STRING "Version of the winjob") find_package(Boost REQUIRED COMPONENTS headers filesystem) find_package(nlohmann_json REQUIRED) -add_executable(winjob src/winjob.cpp src/windows.cpp) +add_executable(winjob src/winjob.cpp src/os.cpp) target_compile_features(winjob PRIVATE cxx_std_23) target_include_directories(winjob PRIVATE ${PROJECT_SOURCE_DIR}/include) -target_link_libraries(winjob PRIVATE Boost::headers Boost::filesystem ws2_32 wsock32) +target_link_libraries(winjob PRIVATE Boost::headers Boost::filesystem) +if(WIN32) + target_link_libraries(winjob PRIVATE ws2_32 wsock32) +endif() target_compile_definitions(winjob PRIVATE winjob_VERSION="${winjob_VERSION}") -add_executable(winjobd src/winjobd.cpp src/windows.cpp) +add_executable(winjobd src/winjobd.cpp src/os.cpp src/scheduler.cpp) target_compile_features(winjob PRIVATE cxx_std_23) target_compile_options(winjobd PRIVATE -fpermissive) target_include_directories(winjobd PRIVATE ${PROJECT_SOURCE_DIR}/include) -target_link_libraries(winjobd PRIVATE Boost::headers Boost::filesystem ws2_32 wsock32) +target_link_libraries(winjobd PRIVATE Boost::headers Boost::filesystem) +if(WIN32) + target_link_libraries(winjobd PRIVATE ws2_32 wsock32) +endif() target_compile_definitions(winjobd PRIVATE winjob_VERSION="${winjob_VERSION}") install(TARGETS winjob RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/local/pkgs/winjob/CMakeLists.txt.user b/local/pkgs/winjob/CMakeLists.txt.user deleted file mode 100644 index 9719f8cf..00000000 --- a/local/pkgs/winjob/CMakeLists.txt.user +++ /dev/null @@ -1,540 +0,0 @@ - - - - - - EnvironmentId - {717c3fd4-7fd4-4144-8aac-caa048cb2e1f} - - - ProjectExplorer.Project.ActiveTarget - 1 - - - ProjectExplorer.Project.EditorSettings - - true - false - true - - Cpp - - CppGlobal - - - - QmlJS - - QmlJSGlobal - - - 2 - UTF-8 - false - 4 - false - 80 - true - true - 1 - 0 - false - true - false - 2 - true - true - 0 - 8 - true - false - 1 - true - true - true - *.md, *.MD, Makefile - false - true - true - - - - ProjectExplorer.Project.PluginSettings - - - true - false - true - true - true - true - - - 0 - true - - true - true - Builtin.DefaultTidyAndClazy - 16 - true - - - - true - - - - - ProjectExplorer.Project.Target.0 - - Desktop - Qt 6.7.2 in PATH (jm3abgh7h0gjhxzcs4gs9h6pv2m5wcgm-qt-full-6.7.2) - Qt 6.7.2 in PATH (jm3abgh7h0gjhxzcs4gs9h6pv2m5wcgm-qt-full-6.7.2) - {b52150f1-39f8-4684-b635-76d19c99973c} - 0 - 0 - 0 - - Debug - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - /home/chn/repo/nixos/local/pkgs/winjob - /home/chn/repo/nixos/local/pkgs/winjob/build - - - - - all - - false - - true - 构建 - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - 构建 - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Debug - CMakeProjectManager.CMakeBuildConfiguration - - 1 - - - 0 - 部署 - 部署 - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph dwarf,4096 -F 250 - - ProjectExplorer.CustomExecutableRunConfiguration - - false - true - true - - 1 - - - - ProjectExplorer.Project.Target.1 - - Desktop - 桌面 - 桌面 - {4cd1732e-0e6c-49a0-8965-8e5466221bf8} - 0 - 0 - 0 - - Debug - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=Debug --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - 0 - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-Debug - - - - - all - - false - - true - 构建 - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - 构建 - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Debug - CMakeProjectManager.CMakeBuildConfiguration - - - Release - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=Release --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-Release - - - - - all - - false - - true - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Release - CMakeProjectManager.CMakeBuildConfiguration - - - RelWithDebInfo - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-RelWithDebInfo - - - - - all - - false - - true - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Release with Debug Information - CMakeProjectManager.CMakeBuildConfiguration - - - RelWithDebInfo - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=RelWithDebInfo --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - 0 - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-Profile - - - - - all - - false - - true - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Profile - CMakeProjectManager.CMakeBuildConfiguration - - - MinSizeRel - 2 - false - - -DCMAKE_GENERATOR:STRING=Unix Makefiles --DCMAKE_BUILD_TYPE:STRING=MinSizeRel --DCMAKE_PROJECT_INCLUDE_BEFORE:FILEPATH=%{BuildConfig:BuildDirectory:NativeFilePath}/.qtc/package-manager/auto-setup.cmake --DQT_QMAKE_EXECUTABLE:FILEPATH=%{Qt:qmakeExecutable} --DCMAKE_PREFIX_PATH:PATH=%{Qt:QT_INSTALL_PREFIX} --DCMAKE_C_COMPILER:FILEPATH=%{Compiler:Executable:C} --DCMAKE_CXX_COMPILER:FILEPATH=%{Compiler:Executable:Cxx} --DCMAKE_CXX_FLAGS_INIT:STRING=%{Qt:QML_DEBUG_FLAG} - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-MinSizeRel - - - - - all - - false - - true - CMakeProjectManager.MakeStep - - 1 - 构建 - 构建 - ProjectExplorer.BuildSteps.Build - - - - - - clean - - false - - true - CMakeProjectManager.MakeStep - - 1 - 清除 - 清除 - ProjectExplorer.BuildSteps.Clean - - 2 - false - - false - - Minimum Size Release - CMakeProjectManager.CMakeBuildConfiguration - - 5 - - - 0 - 部署 - 部署 - ProjectExplorer.BuildSteps.Deploy - - 1 - - false - ProjectExplorer.DefaultDeployConfiguration - - 1 - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph dwarf,4096 -F 250 - winjob - CMakeProjectManager.CMakeRunConfiguration.winjob - winjob - false - true - true - true - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-Debug - - - true - true - 0 - true - - 2 - - false - -e cpu-cycles --call-graph dwarf,4096 -F 250 - winjobd - CMakeProjectManager.CMakeRunConfiguration.winjobd - winjobd - false - true - true - true - /home/chn/repo/nixos/local/pkgs/winjob/build/unknown-Debug - - 2 - - - - ProjectExplorer.Project.TargetCount - 2 - - - ProjectExplorer.Project.Updater.FileVersion - 22 - - - Version - 22 - - diff --git a/local/pkgs/winjob/config.json b/local/pkgs/winjob/config.json new file mode 100644 index 00000000..7de48dec --- /dev/null +++ b/local/pkgs/winjob/config.json @@ -0,0 +1,3 @@ +{ + "cpu": 8 +} diff --git a/local/pkgs/winjob/include/winjob/job.hpp b/local/pkgs/winjob/include/winjob/job.hpp new file mode 100644 index 00000000..c16a8088 --- /dev/null +++ b/local/pkgs/winjob/include/winjob/job.hpp @@ -0,0 +1,17 @@ +# pragma once +# include +# include +# include + +namespace winjob +{ + enum class JobStatus { Pending, Starting, Running, Done, Exit, Canceled, Lost }; + struct Job + { + unsigned Id, Cpu; + std::string User, Program; + std::vector Args; + JobStatus Status; + std::chrono::steady_clock::time_point LastReported, Started, Finished; + }; +} diff --git a/local/pkgs/winjob/include/winjob/scheduler.hpp b/local/pkgs/winjob/include/winjob/scheduler.hpp new file mode 100644 index 00000000..1a5e0a36 --- /dev/null +++ b/local/pkgs/winjob/include/winjob/scheduler.hpp @@ -0,0 +1,27 @@ +# pragma once +# include +# include +# include +# include + +namespace winjob +{ + class Scheduler + { + public: Scheduler(unsigned cpu); + public: ~Scheduler(); + public: std::vector submit(std::vector jobs); + public: void cancel(std::vector jobs); + public: std::vector run(std::vector jobs); + public: std::vector refresh(std::vector jobs); + public: std::vector status(); + + protected: unsigned MaxCpu_, UsedCpu_ = 0; + protected: std::multimap Jobs_; + protected: boost::asio::io_context Context_; + protected: boost::asio::steady_timer Timer_; + protected: bool Destructing_ = false; + protected: std::jthread Executor_; + protected: unsigned NextId_ = 0; + }; +} diff --git a/local/pkgs/winjob/include/winjob/server.hpp b/local/pkgs/winjob/include/winjob/server.hpp new file mode 100644 index 00000000..3a70e1b0 --- /dev/null +++ b/local/pkgs/winjob/include/winjob/server.hpp @@ -0,0 +1,13 @@ +# pragma once +# include +# include +# include + +namespace winjob +{ + class Server + { + public: Server(unsigned port, std::function(std::string)>); + public: ~Server(); + }; +} diff --git a/local/pkgs/winjob/include/winjob/windows.hpp b/local/pkgs/winjob/include/winjob/windows.hpp deleted file mode 100644 index 79186700..00000000 --- a/local/pkgs/winjob/include/winjob/windows.hpp +++ /dev/null @@ -1,9 +0,0 @@ -# include -# include -# include - -namespace winjob -{ - std::optional> get_owner(std::wstring file_name); - bool set_permission(std::wstring fileName); -} diff --git a/local/pkgs/winjob/src/scheduler.cpp b/local/pkgs/winjob/src/scheduler.cpp new file mode 100644 index 00000000..ddd2a18e --- /dev/null +++ b/local/pkgs/winjob/src/scheduler.cpp @@ -0,0 +1,58 @@ +# include +# include + +namespace winjob +{ + using namespace std::literals; + Scheduler::Scheduler(unsigned cpu) + : MaxCpu_(cpu), Timer_(Context_, 1s), Executor_([&] { Context_.run(); }) + { + Timer_.async_wait([&, this](boost::system::error_code) + { + // do not run again if destructing + if (Destructing_) return; + + // check if any job is outdated + std::vector outdated; + auto now = std::chrono::steady_clock::now(); + for (auto it = Jobs_.begin(); it != Jobs_.end();) + if + ( + std::set{JobStatus::Pending, JobStatus::Starting, JobStatus::Running}.contains(it->first) + && now - it->second.LastReported > std::chrono::seconds(30) + ) + { + if (std::set{JobStatus::Starting, JobStatus::Running}.contains(it->first)) + UsedCpu_ -= it->second.Cpu; + outdated.push_back(it->second); + outdated.back().Status = JobStatus::Lost; + it = Jobs_.erase(it); + } + else ++it; + for (auto& job : outdated) Jobs_.insert({JobStatus::Lost, job}); + + // schedule next check + Timer_.expires_at(Timer_.expiry() + 1s); + }); + } + Scheduler::~Scheduler() { Destructing_ = true; Executor_.join(); } + std::vector Scheduler::submit(std::vector jobs) + { + std::vector ids; + boost::asio::dispatch(Context_, [&, this] + { + for (auto& job : jobs) + { + job.Id = NextId_++; + job.Status = JobStatus::Pending; + job.LastReported = std::chrono::steady_clock::now(); + Jobs_.insert({JobStatus::Pending, job}); + ids.push_back(job.Id); + } + }); + return ids; + } + void Scheduler::cancel(unsigned id) {} + bool Scheduler::run(unsigned id) {} + std::vector Scheduler::status() {} +} diff --git a/local/pkgs/winjob/src/server.cpp b/local/pkgs/winjob/src/server.cpp new file mode 100644 index 00000000..e69de29b diff --git a/local/pkgs/winjob/src/windows.cpp b/local/pkgs/winjob/src/windows.cpp deleted file mode 100644 index 66aebd72..00000000 --- a/local/pkgs/winjob/src/windows.cpp +++ /dev/null @@ -1,105 +0,0 @@ -# include -# include -# include -# include -# include - -namespace winjob -{ - std::optional> get_owner(std::wstring file_name) - { - DWORD dwRtnCode = 0; - PSID pSidOwner = NULL; - BOOL bRtnBool = TRUE; - LPWSTR AcctName = NULL; - LPWSTR DomainName = NULL; - DWORD dwAcctName = 1, dwDomainName = 1; - SID_NAME_USE eUse = SidTypeUnknown; - HANDLE hFile; - PSECURITY_DESCRIPTOR pSD = NULL; - - // Get the handle of the file object. - hFile = CreateFileW - (file_name.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - - // Check GetLastError for CreateFile error code. - if (hFile == INVALID_HANDLE_VALUE) return {}; - - // Get the owner SID of the file. - dwRtnCode = GetSecurityInfo(hFile, SE_FILE_OBJECT, OWNER_SECURITY_INFORMATION, &pSidOwner, NULL, NULL, NULL, &pSD); - - // Check GetLastError for GetSecurityInfo error condition. - if (dwRtnCode != ERROR_SUCCESS) return {}; - - // First call to LookupAccountSid to get the buffer sizes. - bRtnBool = LookupAccountSidW - (NULL, pSidOwner, AcctName, (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &eUse); - - // Reallocate memory for the buffers. - AcctName = (LPWSTR)GlobalAlloc(GMEM_FIXED, dwAcctName * sizeof(wchar_t)); - - // Check GetLastError for GlobalAlloc error condition. - if (AcctName == NULL) return {}; - - DomainName = (LPWSTR)GlobalAlloc(GMEM_FIXED, dwDomainName * sizeof(wchar_t)); - - // Check GetLastError for GlobalAlloc error condition. - if (DomainName == NULL) return {}; - - // Second call to LookupAccountSid to get the account name. - bRtnBool = LookupAccountSidW - (NULL, pSidOwner, AcctName, (LPDWORD)&dwAcctName, DomainName, (LPDWORD)&dwDomainName, &eUse); - - // Check GetLastError for LookupAccountSid error condition. - if (bRtnBool == FALSE) return {}; - - return std::make_pair(std::wstring(DomainName), std::wstring(AcctName)); - } - - bool set_permission(std::wstring fileName) - { - // Define the SID for the Users group - PSID pUsersSID = NULL; - SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; - - if (!AllocateAndInitializeSid(&SIDAuthNT, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_USERS, - 0, 0, 0, 0, 0, 0, &pUsersSID)) - return false; - - // Initialize an EXPLICIT_ACCESS structure for an ACE - EXPLICIT_ACCESS ea; - ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); - ea.grfAccessPermissions = GENERIC_WRITE; - ea.grfAccessMode = SET_ACCESS; - ea.grfInheritance = NO_INHERITANCE; - ea.Trustee.TrusteeForm = TRUSTEE_IS_SID; - ea.Trustee.TrusteeType = TRUSTEE_IS_GROUP; - ea.Trustee.ptstrName = (LPTSTR)pUsersSID; - - // Create a new ACL that contains the new ACE - PACL pACL = NULL; - DWORD dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL); - if (ERROR_SUCCESS != dwRes) { FreeSid(pUsersSID); return false; } - - // Initialize a security descriptor - PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH); - if (NULL == pSD) { FreeSid(pUsersSID); LocalFree(pACL); return false; } - - if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) - { FreeSid(pUsersSID); LocalFree(pACL); LocalFree(pSD); return false; } - - // Add the ACL to the security descriptor - if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) - { FreeSid(pUsersSID); LocalFree(pACL); LocalFree(pSD); return false; } - - // Change the security attributes - SECURITY_ATTRIBUTES sa; - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.lpSecurityDescriptor = pSD; - sa.bInheritHandle = FALSE; - - if (!SetFileSecurityW(fileName.c_str(), DACL_SECURITY_INFORMATION, pSD)) - { FreeSid(pUsersSID); LocalFree(pACL); LocalFree(pSD); return false; } - else { FreeSid(pUsersSID); LocalFree(pACL); LocalFree(pSD); return true; } - } -} diff --git a/local/pkgs/winjob/src/winjobd.cpp b/local/pkgs/winjob/src/winjobd.cpp index 502c9915..62b05c95 100644 --- a/local/pkgs/winjob/src/winjobd.cpp +++ b/local/pkgs/winjob/src/winjobd.cpp @@ -1,70 +1,82 @@ -# include -# include -# include -# include +# include +# include +# include # include # include # include -# include +# include using namespace std::literals; int main() { - // clear temp files - std::filesystem::create_directories(LR"(C:\ProgramData\winjob)"); - if (std::filesystem::exists(LR"(C:\ProgramData\winjob\winjobd.sock)")) - std::filesystem::remove(LR"(C:\ProgramData\winjob\winjobd.sock)"); - if (std::filesystem::exists(LR"(C:\ProgramData\winjob\auth)")) - std::filesystem::remove(LR"(C:\ProgramData\winjob\auth)"); - std::filesystem::create_directories(LR"(C:\ProgramData\winjob\auth)"); - winjob::set_permission(LR"(C:\ProgramData\winjob\auth)"); +# ifdef _WIN32 + std::filesystem::path datadir = R"(C:\ProgramData\winjob)"; +# else + std::filesystem::path datadir = "."; +# endif - // log file - std::ofstream log(LR"(C:\ProgramData\winjob\log.txt)", std::ios::app); + // ensure files and directories exist + std::filesystem::create_directories(datadir); + if (std::filesystem::exists(datadir / "winjobd.sock")) std::filesystem::remove(datadir / "winjobd.sock"); + std::ofstream log(datadir / "log.txt", std::ios::app); - auto user = winjob::get_owner(LR"(C:\Users\chn\Desktop\winjob.exe)"); - if (!user) - { - log << "Failed to get owner\n" << std::flush; - return 1; - } - if (user) - { - log << "Owner: " << user->first << "\\" << user->second << '\n' << std::flush; - auto launcher = boost::process::v2::windows::with_logon_launcher(user->second, L"", user->first, - LOGON_WITH_PROFILE); - boost::asio::io_context ctx; - boost::process::v2::error_code ec; - std::wstring program = LR"(C:\Users\chn\Desktop\winjob.exe)"; - auto process = launcher(ctx, ec, program, std::vector{}); - } + // setup scheduler + winjob::Scheduler scheduler(nlohmann::json::parse(std::ifstream(datadir / "config.json"))["cpu"]); - boost::asio::io_context io_context; - boost::asio::local::stream_protocol::endpoint ep(R"(C:\ProgramData\winjob\winjobd.sock)"); - boost::asio::local::stream_protocol::acceptor acceptor(io_context, ep, false); - winjob::set_permission(LR"(C:\ProgramData\winjob\winjobd.sock)"); - std::function func = - [&](const boost::system::error_code& ec, boost::asio::local::stream_protocol::socket socket) - { - if (ec) - { - log << "Failed to accept connection\n" << std::flush; - return; - } - log << "Accepted connection\n" << std::flush; - boost::asio::streambuf buf; - boost::asio::read_until(socket, buf, '\n'); - std::istream is(&buf); - std::string line; - std::getline(is, line); - log << "Received: " << line << '\n' << std::flush; - // write a message to the client - std::string message = "thanks for the message\n"; - boost::asio::write(socket, boost::asio::buffer(message)); - acceptor.async_accept(func); - }; - acceptor.async_accept(func); - io_context.run(); + // setup connection + // boost::asio::io_context io_context; + // std::wstring endpoint = LR"(C:\ProgramData\winjob\winjobd.sock)"; + // boost::asio::local::stream_protocol::acceptor acceptor(io_context, endpoint, false); + // winjob::set_permission(endpoint); +// + // std::function func = + // [&](const boost::system::error_code& ec, boost::asio::local::stream_protocol::socket socket) + // { + // if (ec) log << "Failed to accept connection\n" << std::flush; + // else + // { + // log << "Accepted connection\n" << std::flush; + // boost::asio::streambuf buf; + // boost::asio::read_until(socket, buf, '\n'); + // std::istream is(&buf); + // std::string line; + // std::getline(is, line); + // log << "Received: " << line << '\n' << std::flush; + // // write a message to the client +// +// +// +// +// + // boost::asio::write(socket, boost::asio::buffer(message)); + // acceptor.async_accept(func); + // } + // +// + // }; + // acceptor.async_accept(func); + // io_context.run(); +// +// +// +// + // auto user = winjob::get_owner(LR"(C:\Users\chn\Desktop\winjob.exe)"); + // if (!user) + // { + // log << "Failed to get owner\n" << std::flush; + // return 1; + // } + // if (user) + // { + // log << "Owner: " << user->first << "\\" << user->second << '\n' << std::flush; + // auto launcher = boost::process::v2::windows::with_logon_launcher(user->second, L"", user->first, + // LOGON_WITH_PROFILE); + // boost::asio::io_context ctx; + // boost::process::v2::error_code ec; + // std::wstring program = LR"(C:\Users\chn\Desktop\winjob.exe)"; + // auto process = launcher(ctx, ec, program, std::vector{}); + // } + }