]> git.stg.codes - stg.git/commitdiff
Merge branch 'stg-2.409-radius'
authorMaksym Mamontov <madf@madf.info>
Wed, 1 Jan 2020 19:12:22 +0000 (21:12 +0200)
committerMaksym Mamontov <madf@madf.info>
Wed, 1 Jan 2020 19:12:22 +0000 (21:12 +0200)
1  2 
projects/stargazer/build
projects/stargazer/settings_impl.cpp
projects/stargazer/settings_impl.h
stglibs/common.lib/common.cpp
stglibs/common.lib/include/stg/common.h

diff --combined projects/stargazer/build
index 92935c0537aceb25c85219ccc8dee7e03ab6e9ef,5c2faf268f8d2417c27ca78822c51ae89c5b6037..b5e13df6aee5381b2ff25e1eaeb587b8e162843e
@@@ -105,7 -105,6 +105,6 @@@ PLUGINS="authorization/a
           configuration/sgconfig
           other/ping
           other/rscript
-          other/radius
           other/smux
           store/files
           capture/cap_nf"
@@@ -390,19 -389,6 +389,19 @@@ els
      fi
  fi
  
 +printf "Checking for -lpcap... "
 +printf "#include <pcap.h>\nint main() { return 0; }\n" > build_check.c
 +$CC $CFLAGS $LDFLAGS build_check.c -lpcap -o fake > /dev/null 2> /dev/null
 +if [ $? != 0 ]
 +then
 +    CHECK_PCAP=no
 +    printf "no\n"
 +else
 +    CHECK_PCAP=yes
 +    printf "yes\n"
 +fi
 +rm -f fake
 +
  printf "Checking for -lnfnetlink... "
  printf "#include <stdint.h>\n#include <netinet/in.h>\n#include <linux/netfilter.h>\nint main() { return 0; }\n" > build_check.c
  $CC $CFLAGS $LDFLAGS build_check.c -lnfnetlink -o fake > /dev/null 2> /dev/null
@@@ -431,6 -417,55 +430,55 @@@ els
  fi
  rm -f fake
  
+ printf "Checking for -lyajl... "
+ pkg-config --version > /dev/null 2> /dev/null
+ if [ "$?" = "0" ]
+ then
+     pkg-config --atleast-version=2.0.0 yajl
+     if [ "$?" != "0" ]
+     then
+         CHECK_YAJL=no
+         printf "no\n"
+     else
+         CHECK_YAJL=yes
+         printf `pkg-config --modversion yajl`"\n"
+     fi
+ else
+     printf "#include <stdio.h>\n" > build_check.c
+     printf "#include <yajl/yajl_version.h>\n" >> build_check.c
+     printf "int main() { printf(\"%%d\", yajl_version()); return 0; }\n" >> build_check.c
+     $CC $CFLAGS $LDFLAGS build_check.c -lyajl -o fake > /dev/null 2> /dev/null
+     if [ $? != 0 ]
+     then
+         CHECK_YAJL=no
+         printf "no\n"
+     else
+         YAJL_VERSION=`./fake`
+         if [ $YAJL_VERSION -ge 20000 ]
+         then
+             CHECK_YAJL=yes
+             printf "${YAJL_VERSION}\n"
+         else
+             CHECK_YAJL=no
+             printf "no. Need at least version 2.0.0, existing version is ${YAJL_VERSION}\n"
+         fi
+     fi
+     rm -f fake
+ fi
+ printf "Checking for boost::scoped_ptr... "
+ printf "#include <boost/scoped_ptr.hpp>\nint main() { boost::scoped_ptr<int> test(new int(1)); return 0; }\n" > build_check.cpp
+ $CXX $CXXFLAGS $LDFLAGS build_check.cpp -o fake # > /dev/null 2> /dev/null
+ if [ $? != 0 ]
+ then
+     CHECK_BOOST_SCOPED_PTR=no
+     printf "no\n"
+ else
+     CHECK_BOOST_SCOPED_PTR=yes
+     printf "yes\n"
+ fi
+ rm -f fake
  if [ "$OS" = "linux" ]
  then
      printf "Checking for linux/netfilter_ipv4/ip_queue.h... "
  fi
  
  rm -f build_check.c
+ rm -f build_check.cpp
  
  if [ "$CHECK_EXPAT" != "yes" ]
  then
@@@ -486,18 -522,20 +535,26 @@@ the
               configuration/rpcconfig"
  fi
  
 +if [ "$CHECK_PCAP" = "yes" ]
 +then
 +    PLUGINS="$PLUGINS
 +             capture/pcap"
 +fi
 +
  if [ "$CHECK_NFNETLINK" = "yes" -a "$CHECK_NFQ" = "yes" ]
  then
      PLUGINS="$PLUGINS
               capture/nfqueue"
  fi
  
+ if [ "$CHECK_YAJL" = "yes" -a "$CHECK_BOOST_SCOPED_PTR" = "yes" ]
+ then
+     PLUGINS="$PLUGINS
+              other/radius"
+     STG_LIBS="$STG_LIBS
+               json.lib"
+ fi
  printf "OS=$OS\n" > $CONFFILE
  printf "STG_TIME=yes\n" >> $CONFFILE
  printf "DEBUG=$DEBUG\n" >> $CONFFILE
@@@ -533,7 -571,6 +590,7 @@@ the
      printf "XMLRPC_CFLAGS=$XMLRPC_CFLAGS\n" >> $CONFFILE
      printf "XMLRPC_LDFLAGS=$XMLRPC_LDFLAGS\n" >> $CONFFILE
  fi
 +printf "CHECK_PCAP=$CHECK_PCAP\n" >> $CONFFILE
  printf "CHECK_NFNETLINK=$CHECK_NFNETLINK\n" >> $CONFFILE
  if [ "$CHECK_NFNETLINK" = "yes" ]
  then
index 212ed6343c95bd8e289c044501b3c9dbfd37e539,c925177ffea8c37089d4adc9ee0f77fa378154dd..91258a5f8452855539047ea233e3e3ba2cae5fc6
   *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
- /*
-  *    Date: 27.10.2002
-  */
  /*
   *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
   */
  
- /*
- $Revision: 1.45 $
- $Date: 2010/08/19 13:42:30 $
- $Author: faust $
- */
+ #include "settings_impl.h"
  
+ #include "stg/logger.h"
+ #include "stg/dotconfpp.h"
+ #include "stg/common.h"
+ #include <stdexcept>
  #include <cstring>
  #include <cerrno>
- #include <string>
  
- #include "stg/logger.h"
- #include "stg/dotconfpp.h"
- #include "settings_impl.h"
+ namespace
+ {
+ struct Error : public std::runtime_error
+ {
+     Error(const std::string& message) : runtime_error(message) {}
+ };
+ std::vector<std::string> toValues(const DOTCONFDocumentNode& node)
+ {
+     std::vector<std::string> values;
+     size_t i = 0;
+     const char* value = NULL;
+     while ((value = node.getValue(i++)) != NULL)
+         values.push_back(value);
+     return values;
+ }
+ std::vector<PARAM_VALUE> toPVS(const DOTCONFDocumentNode& node)
+ {
+     std::vector<PARAM_VALUE> pvs;
+     const DOTCONFDocumentNode* child = node.getChildNode();
+     while (child != NULL)
+         {
+         if (child->getName() == NULL)
+             continue;
+         if (child->getChildNode() == NULL)
+             pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child)));
+         else
+             pvs.push_back(PARAM_VALUE(child->getName(), toValues(*child), toPVS(*child)));
+         child = child->getNextNode();
+         }
+     return pvs;
+ }
+ unsigned toPeriod(const char* value)
+ {
+     if (value == NULL)
+         throw Error("No detail stat period value.");
+     std::string period(value);
+     if (period == "1")
+         return dsPeriod_1;
+     else if (period == "1/2")
+         return dsPeriod_1_2;
+     else if (period == "1/4")
+         return dsPeriod_1_4;
+     else if (period == "1/6")
+         return dsPeriod_1_6;
+     throw Error("Invalid detail stat period value: '" + period + "'. Should be one of '1', '1/2', '1/4' or '1/6'.");
+ }
+ }
  
  //-----------------------------------------------------------------------------
  SETTINGS_IMPL::SETTINGS_IMPL(const std::string & cd)
        spreadFee(false),
        freeMbAllowInet(false),
        dayFeeIsLastDay(false),
 +      stopOnError(true),
        writeFreeMbTraffCost(false),
        showFeeInCash(true),
        messageTimeout(0),
  }
  //-----------------------------------------------------------------------------
  SETTINGS_IMPL::SETTINGS_IMPL(const SETTINGS_IMPL & rval)
 -    : SETTINGS(),
 -      strError(),
 -      modulesPath(rval.modulesPath),
 +    : modulesPath(rval.modulesPath),
        dirName(rval.dirName),
        confDir(rval.confDir),
        scriptsDir(rval.scriptsDir),
        spreadFee(rval.spreadFee),
        freeMbAllowInet(rval.freeMbAllowInet),
        dayFeeIsLastDay(rval.dayFeeIsLastDay),
 +      stopOnError(rval.stopOnError),
        writeFreeMbTraffCost(rval.writeFreeMbTraffCost),
        showFeeInCash(rval.showFeeInCash),
        messageTimeout(rval.messageTimeout),
@@@ -125,7 -178,6 +178,7 @@@ SETTINGS_IMPL & SETTINGS_IMPL::operator
      spreadFee = rhs.spreadFee;
      freeMbAllowInet = rhs.freeMbAllowInet;
      dayFeeIsLastDay = rhs.dayFeeIsLastDay;
 +    stopOnError = rhs.stopOnError;
      writeFreeMbTraffCost = rhs.writeFreeMbTraffCost;
      showFeeInCash = rhs.showFeeInCash;
      messageTimeout = rhs.messageTimeout;
      return *this;
  }
  //-----------------------------------------------------------------------------
- int SETTINGS_IMPL::ParseModuleSettings(const DOTCONFDocumentNode * node, std::vector<PARAM_VALUE> * params)
- {
- const DOTCONFDocumentNode * childNode;
- PARAM_VALUE pv;
- const char * value;
- pv.param = node->getName();
- if (node->getValue(1))
-     {
-     strError = "Unexpected value \'" + std::string(node->getValue(1)) + "\'.";
-     return -1;
-     }
- value = node->getValue(0);
- if (!value)
-     {
-     strError = "Module name expected.";
-     return -1;
-     }
- childNode = node->getChildNode();
- while (childNode)
-     {
-     pv.param = childNode->getName();
-     int i = 0;
-     while ((value = childNode->getValue(i++)) != NULL)
-         {
-         pv.value.push_back(value);
-         }
-     params->push_back(pv);
-     pv.value.clear();
-     childNode = childNode->getNextNode();
-     }
- return 0;
- }
- //-----------------------------------------------------------------------------
  void SETTINGS_IMPL::ErrorCallback(void * data, const char * buf)
  {
      printfd(__FILE__, "SETTINGS_IMPL::ErrorCallback() - %s\n", buf);
@@@ -247,11 -260,15 +261,15 @@@ while (node
  
      if (strcasecmp(node->getName(), "DetailStatWritePeriod") == 0)
          {
-         if (ParseDetailStatWritePeriod(node->getValue(0)) != 0)
-             {
-             strError = "Incorrect DetailStatWritePeriod value: \'" + std::string(node->getValue(0)) + "\'";
+         try
+         {
+             detailStatWritePeriod = toPeriod(node->getValue(0));
+         }
+         catch (const Error& error)
+         {
+             strError = error.what();
              return -1;
-             }
+         }
          }
  
      if (strcasecmp(node->getName(), "StatWritePeriod") == 0)
              }
          }
  
 +    if (strcasecmp(node->getName(), "StopOnError") == 0)
 +        {
 +        if (ParseYesNo(node->getValue(0), &stopOnError) != 0)
 +            {
 +            strError = "Incorrect StopOnError value: \'" + std::string(node->getValue(0)) + "\'";
 +            return -1;
 +            }
 +        }
 +
      if (strcasecmp(node->getName(), "WriteFreeMbTraffCost") == 0)
          {
          if (ParseYesNo(node->getValue(0), &writeFreeMbTraffCost) != 0)
              }
          storeModulesCount++;
  
+         if (node->getValue(0) == NULL)
+             {
+             strError = "No module name in the StoreModule section.";
+             return -1;
+             }
          storeModuleSettings.moduleName = node->getValue(0);
-         ParseModuleSettings(node, &storeModuleSettings.moduleParams);
+         storeModuleSettings.moduleParams = toPVS(*node);
          }
  
      if (strcasecmp(node->getName(), "Modules") == 0)
                  child = child->getNextNode();
                  continue;
                  }
-             MODULE_SETTINGS modSettings;
-             modSettings.moduleParams.clear();
-             modSettings.moduleName = child->getValue();
  
-             ParseModuleSettings(child, &modSettings.moduleParams);
+             if (child->getValue(0) == NULL)
+                 {
+                 strError = "No module name in the Module section.";
+                 return -1;
+                 }
  
-             modulesSettings.push_back(modSettings);
+             modulesSettings.push_back(MODULE_SETTINGS(child->getValue(0), toPVS(*child)));
  
              child = child->getNextNode();
              }
  return 0;
  }
  //-----------------------------------------------------------------------------
- int SETTINGS_IMPL::ParseDetailStatWritePeriod(const std::string & detailStatPeriodStr)
- {
- if (detailStatPeriodStr == "1")
-     {
-     detailStatWritePeriod = dsPeriod_1;
-     return 0;
-     }
- else if (detailStatPeriodStr == "1/2")
-     {
-     detailStatWritePeriod = dsPeriod_1_2;
-     return 0;
-     }
- else if (detailStatPeriodStr == "1/4")
-     {
-     detailStatWritePeriod = dsPeriod_1_4;
-     return 0;
-     }
- else if (detailStatPeriodStr == "1/6")
-     {
-     detailStatWritePeriod = dsPeriod_1_6;
-     return 0;
-     }
- return -1;
- }
- //-----------------------------------------------------------------------------
index 113df3ad4ef70cd095e3195dcd2f471ca9037ad7,1e6e2b0df6e0cf04b237e35986fdecef16484799..d9be53f7f84fbe6d6e4c513983c4b0cd3e7723b8
@@@ -1,9 -1,3 +1,3 @@@
-  /*
-  $Revision: 1.27 $
-  $Date: 2010/08/19 13:42:30 $
-  $Author: faust $
-  */
  /*
   *    This program is free software; you can redistribute it and/or modify
   *    it under the terms of the GNU General Public License as published by
   *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   */
  
- /*
-  *    Date: 27.10.2002
-  */
  /*
   *    Author : Boris Mikhailenko <stg34@stargazer.dp.ua>
   */
  
-  /*
-  $Revision: 1.27 $
-  $Date: 2010/08/19 13:42:30 $
-  */
  #ifndef SETTINGS_IMPL_H
  #define SETTINGS_IMPL_H
  
  #include "stg/settings.h"
  #include "stg/common.h"
  #include "stg/module_settings.h"
+ #include "stg/ref.h"
  
  #include <string>
  #include <vector>
  
  //-----------------------------------------------------------------------------
  enum DETAIL_STAT_PERIOD {
- dsPeriod_1,
- dsPeriod_1_2,
- dsPeriod_1_4,
- dsPeriod_1_6
    dsPeriod_1,
    dsPeriod_1_2,
    dsPeriod_1_4,
    dsPeriod_1_6
  };
  //-----------------------------------------------------------------------------
  class STG_LOGGER;
@@@ -58,7 -43,7 +43,7 @@@ class DOTCONFDocumentNode
  class SETTINGS_IMPL : public SETTINGS {
  public:
      explicit SETTINGS_IMPL(const std::string &);
-     SETTINGS_IMPL(const SETTINGS_IMPL &);
+     SETTINGS_IMPL(const SETTINGS_IMPL & rhs);
      virtual ~SETTINGS_IMPL() {}
      SETTINGS_IMPL & operator=(const SETTINGS_IMPL &);
  
@@@ -75,7 -60,7 +60,7 @@@
      const std::string & GetRulesFileName() const { return rules; }
      const std::string & GetLogFileName() const { return logFile; }
      const std::string & GetPIDFileName() const { return pidFile; }
-     unsigned            GetDetailStatWritePeriod() const 
+     unsigned            GetDetailStatWritePeriod() const
          { return detailStatWritePeriod; }
      unsigned            GetStatWritePeriod() const { return statWritePeriod * 60; }
      unsigned            GetDayFee() const { return dayFee; }
@@@ -84,7 -69,6 +69,7 @@@
      bool                GetSpreadFee() const { return spreadFee; }
      bool                GetFreeMbAllowInet() const { return freeMbAllowInet; }
      bool                GetDayFeeIsLastDay() const { return dayFeeIsLastDay; }
 +    bool                GetStopOnError() const { return stopOnError; }
      bool                GetWriteFreeMbTraffCost() const
          { return writeFreeMbTraffCost; }
      bool                GetShowFeeInCash() const { return showFeeInCash; }
  
  private:
  
-     int ParseDetailStatWritePeriod(const std::string & str);
-     int ParseModuleSettings(const DOTCONFDocumentNode * dirNameNode, std::vector<PARAM_VALUE> * params);
      static void ErrorCallback(void * data, const char * buf);
  
      std::string strError;
      std::string modulesPath;
      std::vector<std::string> dirName;
      std::string confDir;
-     std::string       scriptsDir;
+     std::string scriptsDir;
      std::string rules;
      std::string logFile;
      std::string pidFile;
      bool        spreadFee;
      bool        freeMbAllowInet;
      bool        dayFeeIsLastDay;
 +    bool        stopOnError;
      bool        writeFreeMbTraffCost;
      bool        showFeeInCash;
      unsigned    messageTimeout;
  
      std::vector<MODULE_SETTINGS> modulesSettings;
      MODULE_SETTINGS storeModuleSettings;
-     STG_LOGGER & logger;
+     STG::RefWrapper<STG_LOGGER> logger;
  };
  //-----------------------------------------------------------------------------
  
index a4722a00f3e301b9bc84dc6a500552d802dfefbb,7bf27397f38e419a2904f2311ce6b29f64968a40..fcea5ebc23a59b2cc85ca37574b4eb681ae59320
@@@ -32,7 -32,8 +32,8 @@@
  // Like FreeBSD4
  #include <sys/types.h>
  #include <sys/time.h>
- #include <unistd.h>
+ #include <pwd.h>
+ #include <grp.h>
  
  #include <sys/select.h>
  
@@@ -514,22 -515,6 +515,22 @@@ uint32_t inet_strington(const std::stri
      return result;
  }
  //-----------------------------------------------------------------------------
 +std::string TimeToString(time_t time)
 +{
 +struct tm brokenTime;
 +
 +brokenTime.tm_wday = 0;
 +brokenTime.tm_yday = 0;
 +brokenTime.tm_isdst = 0;
 +
 +gmtime_r(&time, &brokenTime);
 +
 +char buf[32];
 +strftime(buf, 32, "%Y-%m-%d %H:%M:%S", &brokenTime);
 +
 +return buf;
 +}
 +//-----------------------------------------------------------------------------
  int ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2)
  {
  char hs1[10], ms1[10], hs2[10], ms2[10];
@@@ -800,6 -785,11 +801,6 @@@ if (errno == ERANGE
  
  return 0;
  }
 -//---------------------------------------------------------------------------
 -int str2x(const std::string & str, double & x)
 -{
 -return strtodouble2(str.c_str(), x);
 -}
  #ifndef WIN32
  //---------------------------------------------------------------------------
  int str2x(const std::string & str, int64_t & x)
@@@ -870,12 -860,6 +871,12 @@@ std::string & Trim(std::string & val
  return TrimR(TrimL(val));
  }
  //---------------------------------------------------------------------------
 +std::string Trim(const std::string & val)
 +{
 +std::string res(val);
 +return TrimR(TrimL(res));
 +}
 +//---------------------------------------------------------------------------
  std::string ToLower(std::string value)
  {
      std::transform(value.begin(), value.end(), value.begin(), ::tolower);
@@@ -1128,3 -1112,37 +1129,37 @@@ std::string ToPrintable(const std::stri
  
      return dest;
  }
+ uid_t str2uid(const std::string& name)
+ {
+     const passwd* res = getpwnam(name.c_str());
+     if (res == NULL)
+         return -1;
+     return res->pw_uid;
+ }
+ gid_t str2gid(const std::string& name)
+ {
+     const group* res = getgrnam(name.c_str());
+     if (res == NULL)
+         return -1;
+     return res->gr_gid;
+ }
+ mode_t str2mode(const std::string& name)
+ {
+     if (name.length() < 3 || name.length() > 4)
+         return -1;
+     if (name.length() == 4 && name[0] != '0')
+         return -1;
+     mode_t res = 0;
+     for (size_t i = 0; i < name.length(); ++i)
+     {
+         if (name[i] > '7' || name[i] < '0')
+             return -1;
+         res = (res << 3) + (name[i] - '0');
+     }
+     return res;
+ }
index a9cc05b1f94e8df0e40e720810023741344fbbca,d404e013a824332976699956b036392f701d579b..1836ae7d3fe1e2a3ba04eb475993f6759d92b9a8
  #ifndef common_h
  #define common_h
  
- #ifdef __BORLANDC__
- #include <time.h>
- #else
- #include <ctime>
- #include <climits> // NAME_MAX
- #endif
+ #include "stg/os_int.h"
+ #include "stg/const.h"
  #include <string>
  #include <sstream>
+ #include <ctime>
+ #include <climits> // NAME_MAX
  
- #include "stg/os_int.h"
- #include "stg/const.h"
+ #include <unistd.h> // uid_t, gid_t
+ #include <sys/stat.h> // mode_t
  
  #define STAT_TIME_3         (1)
  #define STAT_TIME_2         (2)
@@@ -58,8 -57,9 +57,8 @@@ const char    * IntToKMG(int64_t a, in
  const char    * LogDate(time_t t);
  int             ParesTimeStat(const char * str);
  int             IsTimeStat(struct tm * t, int statTime);
 -/*bool            IsDigit(char c);
 -bool            IsAlpha(char c);*/
 -int             strtodouble2(const char * s, double &a);
 +int             strtodouble2(const char * str, double & value);
 +inline int      strtodouble2(const std::string & str, double & value) { return strtodouble2(str.c_str(), value); }
  int             printfd(const char * __file__, const char * fmt, ...);
  void            Encode12(char * dst, const char * src, size_t srcLen);
  void            Decode21(char * dst, const char * src);
@@@ -77,9 -77,9 +76,9 @@@ void            WinToKOI(const std::str
  int             DaysInMonth(unsigned year, unsigned mon);
  int             DaysInCurrentMonth();
  int             Min8(int a);
 -//char          * inet_ntostr(unsigned long);
  std::string     inet_ntostring(uint32_t);
  uint32_t        inet_strington(const std::string & value);
 +std::string     TimeToString(time_t time);
  int             strprintf(std::string * str, const char * fmt, ...);
  int             ParseTariffTimeStr(const char * str, int &h1, int &m1, int &h2, int &m2);
  uint32_t        CalcMask(uint32_t msk);
@@@ -98,13 -98,11 +97,13 @@@ void            SwapBytes(int64_t & val
  std::string &   TrimL(std::string & val);
  std::string &   TrimR(std::string & val);
  std::string &   Trim(std::string & val);
 +std::string     Trim(const std::string & val);
  
 -std::string ToLower(std::string value);
 -std::string ToUpper(std::string value);
 +std::string     ToLower(std::string value);
 +std::string     ToUpper(std::string value);
  
  template <typename C, typename F>
 +inline
  C Split(const std::string & value, char delim, F conv)
  {
  C res;
@@@ -121,7 -119,6 +120,7 @@@ return res
  }
  
  template <typename T>
 +inline
  T FromString(const std::string & value)
  {
  T res;
@@@ -130,18 -127,10 +129,18 @@@ stream >> res
  return res;
  }
  
 +template <>
 +inline
 +std::string FromString<std::string>(const std::string & value)
 +{
 +return value;
 +}
 +
  template <typename C>
 +inline
  C Split(const std::string & value, char delim)
  {
 -    return Split<C>(value, delim, FromString);
 +    return Split<C>(value, delim, FromString<typename C::value_type>);
  }
  
  std::string IconvString(const std::string & source, const std::string & from, const std::string & to);
@@@ -165,8 -154,7 +164,8 @@@ time_t readTime(const std::string & val
  //-----------------------------------------------------------------------------
  int str2x(const std::string & str, int32_t & x);
  int str2x(const std::string & str, uint32_t & x);
 -int str2x(const std::string & str, double & x);
 +inline
 +int str2x(const std::string & str, double & x) { return strtodouble2(str.c_str(), x); }
  #ifndef WIN32
  int str2x(const std::string & str, int64_t & x);
  int str2x(const std::string & str, uint64_t & x);
@@@ -223,7 -211,7 +222,7 @@@ int str2x(const std::string & str, var
          x += str[i] - '0';
      }
  
 -    x*= minus;
 +    x *= minus;
  
      return 0;
  }
@@@ -314,4 -302,8 +313,8 @@@ const std::string & unsigned2str(varT x
  char * stg_strptime(const char *, const char *, struct tm *);
  time_t stg_timegm(struct tm *);
  
+ uid_t str2uid(const std::string& name);
+ gid_t str2gid(const std::string& name);
+ mode_t str2mode(const std::string& mode);
  #endif