[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/ssh352/rstudio/main/src/cpp/core/system/System.cpp [Back]  [Original]

/*
 * System.cpp
 *
 * Copyright (C) 2022 by Posit Software, PBC
 *
 * Unless you have received this program directly from Posit Software pursuant
 * to the terms of a commercial license agreement with Posit Software, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#define RSTUDIO_DEBUG_MACROS_DISABLED

#include 
#include 

#include 

#include 
#include 
#include 
#include 
#include 

#ifndef _WIN32
#include 
#endif

#include 
#include 
#include 
#include 
#include 

namespace rstudio {
namespace core {
namespace system {

#ifdef _WIN32
#define kPathSeparator ";"
#else
#define kPathSeparator ":"
#endif


bool realPathsEqual(const FilePath& a, const FilePath& b)
{
   FilePath aReal, bReal;

   Error error = realPath(a, &aReal);
   if (error)
   {
      LOG_ERROR(error);
      return false;
   }

   error = realPath(b, &bReal);
   if (error)
   {
      LOG_ERROR(error);
      return false;
   }

   return aReal == bReal;
}

void addToSystemPath(const FilePath& path, bool prepend)
{
   std::string systemPath = system::getenv("PATH");
   if (prepend)
      systemPath = path.getAbsolutePath() + kPathSeparator + systemPath;
   else
      systemPath = systemPath + kPathSeparator + path.getAbsolutePath();
   system::setenv("PATH", systemPath);
}

int exitFailure(const Error& error, const ErrorLocation& loggedFromLocation)
{
   if (error)
      core::log::logError(error, loggedFromLocation);
   return EXIT_FAILURE;
}

int exitFailure(const std::string& errMsg,
                const ErrorLocation& loggedFromLocation)
{
   core::log::logErrorMessage(errMsg, loggedFromLocation);
   return EXIT_FAILURE;
}
   
int exitSuccess()
{
   return EXIT_SUCCESS;
}

std::string generateShortenedUuid()
{
   std::string uuid = core::system::generateUuid(false);
   return core::hash::crc32HexHash(uuid);
}

// logger's program identity (this process's binary name)
std::string s_programIdentity;

// logging options representing the latest state of the logging configuration file
boost::shared_ptr s_logOptions;

// mutex for logging synchronization
boost::recursive_mutex s_loggingMutex;

namespace {

void initializeLogWriter()
{
   using namespace log;

   // requires prior synchronization
   LoggerType loggerType = s_logOptions->loggerType();
   LogMessageFormatType formatType = s_logOptions->logMessageFormatType();

   // options currently only used for file logging
   LoggerOptions options = s_logOptions->loggerOptions();

   log::LogLevel logLevel = s_logOptions->logLevel();

   switch (loggerType)
   {
      case LoggerType::kFile:
      {
         FileLogDestination* dst = new FileLogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               s_programIdentity,
               boost::get(options),
               true);
         addLogDestination(
            std::shared_ptr(dst));
         ttyCheck(dst->path());
         break;
      }
      case LoggerType::kStdErr:
      {
         addLogDestination(
            std::shared_ptr(new StderrLogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               true)));
         break;
      }
      case LoggerType::kSysLog:
      default:
      {
#ifndef _WIN32
         addLogDestination(
            std::shared_ptr(new SyslogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               s_programIdentity,
               true)));
         ttyCheck("syslog");
#endif
      }
   }
}

void initializeLogWriter(const std::string& logSection)
{
   using namespace log;

   // requires prior synchronization
   LoggerType loggerType = s_logOptions->loggerType(logSection);
   LogMessageFormatType formatType = s_logOptions->logMessageFormatType(logSection);

   // options currently only used for file logging
   LoggerOptions options = s_logOptions->loggerOptions(logSection);

   log::LogLevel logLevel = s_logOptions->logLevel(logSection);

   switch (loggerType)
   {
      case LoggerType::kFile:
      {
         addLogDestination(
            std::shared_ptr(new FileLogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               s_programIdentity,
               boost::get(options),
               true)), logSection);
         break;
      }
      case LoggerType::kStdErr:
      {
         addLogDestination(
            std::shared_ptr(new StderrLogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               true)), logSection);
         break;
      }
      case LoggerType::kSysLog:
      default:
      {
#ifndef _WIN32
         addLogDestination(
            std::shared_ptr(new SyslogDestination(
               generateShortenedUuid(),
               logLevel,
               formatType,
               s_programIdentity,
               true)), logSection);
#endif
      }
   }
}

void initializeLogWriters()
{
   // requires prior synchronization
   log::setProgramId(s_programIdentity);

   // Initialize primary log writer
   initializeLogWriter();

   // Initialize secondary log writers
   std::vector logSections = s_logOptions->loggerOverrides();
   for (const std::string& loggerName : logSections)
      initializeLogWriter(loggerName);
}

} // anonymous namespace

void ttyCheck(const std::string& destination)
{
   // When running in a TTY, log some information about why we're logging to the TTY
   // in addition to file/syslog.
   if (stderrIsTerminal())
      std::cerr data = boost::shared_ptr(new ProcessInfo(process));

         (*pOutTree)[process.pid] = nodePtr;
      }
   }

   // second pass, link the nodes together
   for (ProcessTreeT::value_type& element : *pOutTree)
   {
      PidType parent = element.second->data->ppid;
      ProcessTreeT::iterator iter = pOutTree->find(parent);

      // if we cannot find the parent in the tree, move on
      if (iter == pOutTree->end())
         continue;

      // add this node to its parent's children
      iter->second->children.push_back(element.second);
   }
}

void getChildren(const boost::shared_ptr& node,
                 std::vector* pOutChildren,
                 int depth)
{
   std::unordered_set visited;
   for (const boost::shared_ptr& child : node->children)
   {
      // cycle protection - only visit the node and its children if it hasn't been visited already
      // depth protection - do not infinitely recurse for process creation bombs
      if (visited.count(child->data->pid) == 0 && depth < 100)
      {
         visited.insert(child->data->pid);
         pOutChildren->push_back(*child->data.get());
         getChildren(child, pOutChildren, depth + 1);
      }
   }
}

} // namespace system
} // namespace core
} // namespace rstudio


Web Proxy Viewer  |  New URL  |  Original Page