Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2021-02-14 13:29:22

0001 //------------------------------------------------------------
0002 //------------------------------------------------------------
0003 #include <cerrno>
0004 #include <cstdlib>
0005 #include <exception>
0006 #include <filesystem>
0007 #include <iostream>
0008 #include <string>
0009 
0010 #include <sys/wait.h>
0011 #include <unistd.h>
0012 #include <cstring>
0013 
0014 #include "FWCore/Utilities/interface/EDMException.h"
0015 #include "FWCore/Utilities/interface/Exception.h"
0016 #include "FWCore/Utilities/interface/RegexMatch.h"
0017 #include "FWCore/Utilities/interface/TestHelper.h"
0018 #include "FWCore/Utilities/interface/thread_safety_macros.h"
0019 
0020 namespace bf = std::filesystem;
0021 
0022 int run_script(std::string const& shell, std::string const& script) {
0023   pid_t pid = 0;
0024   int status = 0;
0025 
0026   if ((pid = fork()) < 0) {
0027     std::cerr << "fork failed, to run " << script << std::endl;
0028     return -1;
0029   }
0030 
0031   if (pid == 0) {  // child
0032     execlp(shell.c_str(), "sh", "-c", script.c_str(), static_cast<char const*>(nullptr));
0033     std::cerr << "child failed becuase '" << strerror(errno) << "'\n";
0034     _exit(127);  // signal parent and children processes
0035   } else {       // parent
0036     while (waitpid(pid, &status, 0) < 0) {
0037       if (errno != EINTR) {
0038         std::cerr << "child process failed " << strerror(errno) << "\n";
0039         status = -1;
0040         break;
0041       } else {
0042         if (WIFSIGNALED(status)) {
0043           std::cerr << "child existed because of a signal " << WTERMSIG(status) << "\n";
0044         }
0045       }
0046     }
0047     if (WIFSIGNALED(status)) {
0048       std::cerr << "child existed because of a signal " << WTERMSIG(status) << "\n";
0049     }
0050     if (WIFEXITED(status)) {
0051     }
0052   }
0053   return status;
0054 }
0055 
0056 int do_work(int argc, char* argv[], char** env) {
0057   bf::path currentPath(bf::current_path().string());
0058 
0059   if (argc < 4) {
0060     std::cout << "Usage: " << argv[0] << " shell subdir script1 script2 ... scriptN\n\n"
0061               << "where shell is the path+shell (e.g., /bin/bash) intended to run the scripts\n"
0062               << "and subdir is the subsystem/package/subdir in which the scripts are found\n"
0063               << "(e.g., FWCore/Utilities/test)\n"
0064               << std::endl;
0065 
0066     std::cout << "Current directory is: " << currentPath.string() << '\n';
0067     std::cout << "Current environment:\n";
0068     std::cout << "---------------------\n";
0069     for (int i = 0; env[i] != nullptr; ++i)
0070       std::cout << env[i] << '\n';
0071     std::cout << "---------------------\n";
0072     std::cout << "Executable name: " << argv[0] << '\n';
0073     return -1;
0074   }
0075 
0076   char const* goodDirectory = "[A-Za-z0-9/_.-]+";
0077 
0078   for (int i = 0; i < argc; ++i) {
0079     std::cout << "argument " << i << ": " << argv[i] << '\n';
0080   }
0081 
0082   std::string shell(argv[1]);
0083   std::cerr << "shell is: " << shell << '\n';
0084 
0085   std::cout << "Current directory is: " << currentPath.string() << '\n';
0086   // It is unclear about which of these environment variables should
0087   // be used.
0088   char const* topdir = std::getenv("SCRAMRT_LOCALRT");
0089   if (!topdir)
0090     topdir = std::getenv("LOCALRT");
0091   try {
0092     if (!edm::untaintString(topdir, goodDirectory)) {
0093       std::cerr << "Invalid top directory '" << topdir << "'" << std::endl;
0094       return -1;
0095     }
0096   } catch (std::runtime_error const& e) {
0097     std::cerr << "Invalid top directory '" << topdir << "'" << std::endl;
0098     std::cerr << "e.what" << std::endl;
0099     return -1;
0100   }
0101 
0102   char const* arch = std::getenv("SCRAM_ARCH");
0103 
0104   if (!arch) {
0105     // Try to synthesize SCRAM_ARCH value.
0106     bf::path exepath(argv[0]);
0107     std::string maybe_arch = exepath.parent_path().filename().string();
0108 
0109     if (setenv("SCRAM_ARCH", maybe_arch.c_str(), 1) != 0) {
0110       std::cerr << "SCRAM_ARCH not set and attempt to set it failed\n";
0111       return -1;
0112     }
0113     arch = std::getenv("SCRAM_ARCH");
0114   }
0115 
0116   int rc = 0;
0117 
0118   if (!topdir) {
0119     std::cerr << "Neither SCRAMRT_LOCALRT nor LOCALRT is defined" << std::endl;
0120     return -1;
0121   }
0122 
0123   try {
0124     if (!edm::untaintString(argv[2], goodDirectory)) {
0125       std::cerr << "Invalid test directory '" << argv[2] << "'" << std::endl;
0126       return -1;
0127     }
0128   } catch (std::runtime_error const& e) {
0129     std::cerr << "Invalid test directory '" << argv[2] << "'" << std::endl;
0130     std::cerr << "e.what" << std::endl;
0131     return -1;
0132   }
0133 
0134   std::string testdir(topdir);
0135   testdir += "/src/";
0136   testdir += argv[2];
0137   std::string tmpdir(topdir);
0138   tmpdir += "/tmp/";
0139   tmpdir += arch;
0140   std::string testbin(topdir);
0141   testbin += "/test/";
0142   testbin += arch;
0143 
0144   std::cout << "topdir is: " << topdir << '\n';
0145   std::cout << "testdir is: " << testdir << '\n';
0146   std::cout << "tmpdir is: " << tmpdir << '\n';
0147   std::cout << "testbin is: " << testbin << '\n';
0148 
0149   if (setenv("LOCAL_TEST_DIR", testdir.c_str(), 1) != 0) {
0150     std::cerr << "Could not set LOCAL_TEST_DIR to " << testdir << std::endl;
0151     return -1;
0152   }
0153   if (setenv("LOCAL_TMP_DIR", tmpdir.c_str(), 1) != 0) {
0154     std::cerr << "Could not set LOCAL_TMP_DIR to " << tmpdir << std::endl;
0155     return -1;
0156   }
0157   if (setenv("LOCAL_TOP_DIR", topdir, 1) != 0) {
0158     std::cerr << "Could not set LOCAL_TOP_DIR to " << topdir << std::endl;
0159     return -1;
0160   }
0161   if (setenv("LOCAL_TEST_BIN", testbin.c_str(), 1) != 0) {
0162     std::cerr << "Could not set LOCAL_TEST_BIN to " << testbin << std::endl;
0163     return -1;
0164   }
0165 
0166   testdir += "/";
0167 
0168   for (int i = 3; i < argc && rc == 0; ++i) {
0169     std::string scriptname(testdir);
0170     scriptname += argv[i];
0171     std::cout << "Running script: " << scriptname << std::endl;
0172     rc = run_script(shell, scriptname);
0173   }
0174 
0175   std::cout << "status = " << rc << std::endl;
0176   return rc == 0 ? 0 : -1;
0177 }
0178 
0179 int ptomaine(int argc, char* argv[], char** env) {
0180   int rc = 1;
0181   // Standalone executable, prints exception message
0182   CMS_SA_ALLOW try { rc = do_work(argc, argv, env); } catch (edm::Exception& x) {
0183     std::cerr << "Caught an edm::Exception in " << argv[0] << '\n' << x;
0184   } catch (cms::Exception& x) {
0185     std::cerr << "Caught a cms::Exception in " << argv[0] << '\n' << x;
0186   } catch (std::exception& x) {
0187     std::cerr << "Caught a std::exception in " << argv[0] << '\n' << x.what();
0188   } catch (...) {
0189     std::cerr << "Caught an unknown exception in " << argv[0];
0190   }
0191   return rc;
0192 }