File indexing completed on 2026-04-09 07:49:48
0001 #pragma once
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <cstdlib>
0011 #include <cassert>
0012 #include <cstring>
0013 #include <string>
0014 #include <regex>
0015 #include <sstream>
0016 #include <vector>
0017 #include <iostream>
0018 #include <iomanip>
0019 #include <map>
0020 #include <limits>
0021 #include <cstdint>
0022
0023 #include "sstr.h"
0024 #include "spath.h"
0025
0026 extern char **environ;
0027
0028 struct ssys
0029 {
0030 static constexpr const bool VERBOSE = false ;
0031 static constexpr const char* GETENVVAR_PATH_PREFIX = "filepath:" ;
0032
0033
0034 static std::string popen(const char* cmd, bool chomp=true, int* rc=nullptr);
0035 static std::string popen(const char* cmda, const char* cmdb, bool chomp=true, int* rc=nullptr);
0036
0037 static std::string uname(const char* args="-a");
0038 static std::string which(const char* script);
0039
0040 static bool value_is_path_prefixed(const char* val );
0041 static const char* get_replacement_path(const char* val );
0042
0043 static std::string getenviron(const char* q=nullptr);
0044 static bool is_under_ctest();
0045
0046 static const char* getenvvar(const char* ekey );
0047 static const char* getenvvar(const char* ekey, const char* fallback);
0048 static const char* getenvvar(const char* ekey, const char* fallback, char q, char r );
0049
0050
0051
0052
0053
0054 static int64_t getenv_ParseInt64(const char* ekey, const char* fallback);
0055 static std::vector<int64_t>* getenv_ParseInt64SpecList(const char* ekey, const char* fallback);
0056
0057 static unsigned long long getenvull(const char* ekey, unsigned long long fallback);
0058 static int getenvint(const char* ekey, int fallback);
0059 static int64_t getenvint64(const char* ekey, int64_t fallback);
0060
0061 static int64_t getenvint64spec( const char* ekey, const char* fallback);
0062 static uint64_t getenvuint64spec(const char* ekey, const char* fallback );
0063
0064 static int getenvintpick( const char* ekey, const std::vector<std::string>& strs, int fallback );
0065
0066 static unsigned getenvunsigned(const char* ekey, unsigned fallback);
0067 static unsigned getenvunsigned_fallback_max(const char* ekey );
0068
0069
0070
0071 static double getenvdouble(const char* ekey, double fallback);
0072 static float getenvfloat(const char* ekey, float fallback);
0073 static bool getenvbool(const char* ekey);
0074
0075
0076 static int countenv(const char* ekey, char delim=',');
0077
0078 static bool hasenv_(const char* ekey);
0079 static bool hastoken_(const char* ekey);
0080 static char* _getenv(const char* ekey);
0081 static char* replace_envvar_token(const char* ekey);
0082 static char* _replace_envvar_token(const char* ekey);
0083 static char* _tokenized_getenv(const char* ekey);
0084
0085
0086 template<typename T>
0087 static T parse(const char* str);
0088
0089
0090 template<typename T>
0091 static T getenv_(const char* ekey, T fallback);
0092
0093 template<typename T>
0094 static void getenv_(std::vector<std::pair<std::string, T>>& kv, const std::vector<std::string>& kk );
0095
0096 template<typename T>
0097 static void getenv_(std::vector<std::pair<std::string, T>>& kv, const char* kk );
0098
0099 template<typename T>
0100 static void fill_vec( std::vector<T>& vec, const char* line, char delim=',' );
0101
0102 template<typename T>
0103 static void fill_evec( std::vector<T>& vec, const char* ekey, const char* fallback, char delim );
0104
0105
0106 template<typename T>
0107 static std::vector<T>* make_vec(const char* line, char delim=',');
0108
0109 template<typename T>
0110 static std::vector<T>* getenv_vec(const char* ekey, const char* fallback, char delim=',');
0111
0112
0113 static std::vector<int>* getenvintvec( const char* envkey, char delim=',');
0114 static void getenvintvec( const char* ekey, std::vector<int>& vec, char delim, const char* fallback ) ;
0115 static std::vector<float>* getenvfloatvec(const char* envkey, const char* fallback, char delim=',');
0116
0117
0118 template<typename T>
0119 static std::string desc_vec( const std::vector<T>* vec, unsigned edgeitems=5 );
0120
0121 static int idx_listed( const std::vector<std::string>* nn, const char* n );
0122 static bool is_listed( const std::vector<std::string>* nn, const char* n );
0123 static int listed_count( std::vector<int>* ncount, const std::vector<std::string>* nn, const char* n );
0124 static std::string desc_listed_count( const std::vector<int>* ncount, const std::vector<std::string>* nn );
0125
0126 static bool is_remote_session();
0127 static const char* username();
0128
0129 static void Dump(const char* msg);
0130 static int run(const char* cmd);
0131
0132 static int setenvvar( const char* ekey, const char* value, bool overwrite=true, char special_empty_token='\0' );
0133 static int setenvmap( const std::map<std::string, std::string>& env, bool overwrite=true , char special_empty_token='\0' );
0134
0135 template<typename ... Args>
0136 static int setenvctx( Args ... args );
0137
0138 static std::string Desc();
0139 static std::string PWD();
0140
0141 static void getenv_with_prefix(std::vector<std::pair<std::string,std::string>>& kvs, const char* prefix) ;
0142
0143
0144 };
0145
0146
0147 inline std::string ssys::popen(const char* cmd, bool chomp, int* rc)
0148 {
0149 std::stringstream ss ;
0150 FILE *fp = ::popen(cmd, "r");
0151 char line[512];
0152 while (fgets(line, sizeof(line), fp) != NULL)
0153 {
0154 if(chomp) line[strcspn(line, "\n")] = 0;
0155 ss << line ;
0156 }
0157
0158 int retcode=0 ;
0159 int st = pclose(fp);
0160 if(WIFEXITED(st)) retcode=WEXITSTATUS(st);
0161
0162 if(rc) *rc = retcode ;
0163
0164 std::string s = ss.str();
0165 return s ;
0166 }
0167
0168 inline std::string ssys::popen(const char* cmda, const char* cmdb, bool chomp, int* rc)
0169 {
0170 std::stringstream ss ;
0171 if(cmda) ss << cmda ;
0172 ss << " " ;
0173 if(cmdb) ss << cmdb ;
0174
0175 std::string s = ss.str();
0176 return popen(s.c_str(), chomp, rc );
0177 }
0178
0179 inline std::string ssys::uname(const char* args)
0180 {
0181 bool chomp = true ;
0182 int rc(0);
0183 std::string line = ssys::popen("uname", args, chomp, &rc );
0184 return rc == 0 ? line : "" ;
0185 }
0186
0187
0188 inline std::string ssys::which(const char* script)
0189 {
0190 bool chomp = true ;
0191 int rc(0);
0192 std::string path = ssys::popen("which 2>/dev/null", script, chomp, &rc );
0193
0194 if(VERBOSE) std::cerr
0195 << " script " << script
0196 << " path " << path
0197 << " rc " << rc
0198 << std::endl
0199 ;
0200
0201 std::string empty ;
0202 return rc == 0 ? path : empty ;
0203 }
0204
0205
0206
0207 inline bool ssys::value_is_path_prefixed(const char* val )
0208 {
0209 return val && strlen(val) > strlen(GETENVVAR_PATH_PREFIX) && strncmp(val, GETENVVAR_PATH_PREFIX, strlen(GETENVVAR_PATH_PREFIX)) == 0 ;
0210 }
0211
0212 inline const char* ssys::get_replacement_path(const char* val )
0213 {
0214 assert(value_is_path_prefixed(val)) ;
0215 return val ? strdup(val + strlen(GETENVVAR_PATH_PREFIX)) : nullptr ;
0216 }
0217
0218
0219
0220 inline std::string ssys::getenviron(const char* q)
0221 {
0222 char** e = environ ;
0223 std::stringstream ss ;
0224 while(*e)
0225 {
0226 if( q == nullptr || strstr(*e, q)) ss << *e << "\n" ;
0227 e++ ;
0228 }
0229 std::string str = ss.str();
0230 return str;
0231 }
0232
0233 inline bool ssys::is_under_ctest()
0234 {
0235 return countenv("DASHBOARD_TEST_FROM_CTEST,DART_TEST_FROM_DART", ',') > 0 ;
0236 }
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 inline const char* ssys::getenvvar(const char* ekey)
0261 {
0262 std::vector<std::string> keys ;
0263 sstr::Split(ekey, ',', keys) ;
0264 char* val = getenv(ekey);
0265 for(unsigned i=0 ; i < keys.size() ; i++)
0266 {
0267 const char* key = keys[i].c_str();
0268 val = getenv(key) ;
0269 if( val != nullptr ) break ;
0270 }
0271
0272 bool is_path_prefixed = value_is_path_prefixed(val) ;
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283 if(is_path_prefixed)
0284 {
0285 const char* path = get_replacement_path(val) ;
0286
0287 std::string txt ;
0288 bool path_exists = spath::Read( txt, path );
0289 val = path_exists ? strdup(txt.c_str()) : nullptr ;
0290
0291 if(VERBOSE) std::cout
0292 << "ssys::getenvvar.is_path_prefixed "
0293 << " ekey " << ( ekey ? ekey : "-" )
0294 << " path " << ( path ? path : "-" )
0295 << " path_exists " << ( path_exists ? "YES" : "NO " )
0296 << " val " << ( val ? val : "-" )
0297 << std::endl
0298 ;
0299
0300 }
0301 return val ;
0302 }
0303 inline const char* ssys::getenvvar(const char* ekey, const char* fallback)
0304 {
0305 const char* val = getenvvar(ekey);
0306 return ( val && strlen(val)>0) ? val : fallback ;
0307 }
0308 inline const char* ssys::getenvvar(const char* ekey, const char* fallback, char q, char r)
0309 {
0310 const char* v = getenvvar(ekey, fallback) ;
0311 char* vv = v ? strdup(v) : nullptr ;
0312 for(int i=0 ; i < int(vv ? strlen(vv) : 0) ; i++) if(vv[i] == q ) vv[i] = r ;
0313 return vv ;
0314 }
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329
0330
0331
0332
0333
0334
0335
0336
0337
0338
0339
0340 inline int64_t ssys::getenv_ParseInt64(const char* ekey, const char* fallback)
0341 {
0342 const char* spec = getenvvar(ekey, fallback);
0343 bool valid = spec != nullptr && strlen(spec) > 0 ;
0344 if(!valid)
0345 {
0346 std::cerr
0347 << "ssys::getenv_ParseInt64"
0348 << " ekey " << ( ekey ? ekey : "-" )
0349 << " fallback " << ( fallback ? fallback : "-" )
0350 << " spec [" << ( spec ? spec : "-" ) << "]"
0351 << " valid " << ( valid ? "YES" : "NO " )
0352 << "\n"
0353 ;
0354
0355 return -1 ;
0356 }
0357 return sstr::ParseInt<int64_t>(spec) ;
0358 }
0359
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 inline std::vector<int64_t>* ssys::getenv_ParseInt64SpecList(const char* ekey, const char* fallback)
0380 {
0381 const char* spec = getenvvar(ekey, fallback);
0382 bool valid = spec != nullptr && strlen(spec) > 0 ;
0383 if(!valid) return nullptr ;
0384 return sstr::ParseIntSpecList<int64_t>( spec, ',' );
0385 }
0386
0387
0388 inline unsigned long long ssys::getenvull(const char* ekey, unsigned long long fallback)
0389 {
0390 char* val = getenv(ekey);
0391 return val ? std::atoll(val) : fallback ;
0392 }
0393
0394
0395
0396 inline int ssys::getenvint(const char* ekey, int fallback)
0397 {
0398 char* val = getenv(ekey);
0399 return val ? std::atoi(val) : fallback ;
0400 }
0401
0402 inline int64_t ssys::getenvint64(const char* ekey, int64_t fallback)
0403 {
0404 char* val = getenv(ekey);
0405 return val ? std::atol(val) : fallback ;
0406 }
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 inline int64_t ssys::getenvint64spec(const char* ekey, const char* fallback)
0431 {
0432 char* val = getenv(ekey);
0433 const char* spec = val ? val : fallback ;
0434 int64_t ival = sstr::ParseInt<int64_t>( spec ? spec : "0" );
0435 return ival ;
0436 }
0437
0438 inline uint64_t ssys::getenvuint64spec(const char* ekey, const char* fallback)
0439 {
0440 char* val = getenv(ekey);
0441 const char* spec = val ? val : fallback ;
0442 uint64_t ival = sstr::ParseInt<uint64_t>( spec ? spec : "0" );
0443 return ival ;
0444 }
0445
0446
0447 inline int ssys::getenvintpick(const char* ekey, const std::vector<std::string>& strs, int fallback )
0448 {
0449 char* v = getenv(ekey);
0450 if(v == nullptr) return fallback ;
0451
0452 int pick = fallback ;
0453 int num_str = strs.size() ;
0454 for(int i=0 ; i < num_str ; i++)
0455 {
0456 const char* str = strs[i].c_str();
0457 if( str && v && strcmp(str, v) == 0 )
0458 {
0459 pick = i ;
0460 break ;
0461 }
0462 }
0463 return pick ;
0464 }
0465
0466
0467
0468
0469
0470
0471
0472 inline unsigned ssys::getenvunsigned(const char* ekey, unsigned fallback)
0473 {
0474 int ival = getenvint(ekey, int(fallback));
0475 return ival > -1 ? ival : fallback ;
0476 }
0477 inline unsigned ssys::getenvunsigned_fallback_max(const char* ekey)
0478 {
0479 return getenvunsigned(ekey, std::numeric_limits<unsigned>::max() );
0480 }
0481
0482
0483 inline bool ssys::getenvbool( const char* ekey )
0484 {
0485 char* val = getenv(ekey);
0486 bool ival = val ? true : false ;
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500 return ival ;
0501 }
0502
0503 inline float ssys::getenvfloat( const char* ekey, float fallback){ return getenv_<float>(ekey, fallback) ; }
0504 inline double ssys::getenvdouble(const char* ekey, double fallback){ return getenv_<double>(ekey, fallback) ; }
0505
0506
0507
0508
0509
0510
0511
0512
0513 inline int ssys::countenv(const char* ekey, char delim)
0514 {
0515 std::vector<std::string> keys ;
0516 sstr::Split(ekey, delim, keys) ;
0517
0518 int count = 0 ;
0519 char* val = nullptr ;
0520 for(unsigned i=0 ; i < keys.size() ; i++)
0521 {
0522 const char* key = keys[i].c_str();
0523 val = getenv(key) ;
0524 if( val != nullptr ) count += 1 ;
0525 }
0526 return count ;
0527 }
0528
0529
0530 inline bool ssys::hasenv_(const char* ekey)
0531 {
0532 return ekey != nullptr && ( getenv(ekey) != nullptr ) ;
0533 }
0534
0535 inline bool ssys::hastoken_(const char* ekey)
0536 {
0537 return ekey != nullptr && strstr(ekey, "${") != nullptr && strstr(ekey, "}") != nullptr ;
0538 }
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551 inline char* ssys::_getenv(const char* ekey)
0552 {
0553 if(ekey == nullptr) return nullptr ;
0554 return !hastoken_(ekey) ? getenv(ekey) : _tokenized_getenv(ekey ) ;
0555 }
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569 inline char* ssys::replace_envvar_token(const char* ekey)
0570 {
0571 return !hastoken_(ekey) ? strdup(ekey) : _replace_envvar_token(ekey ) ;
0572 }
0573 inline char* ssys::_replace_envvar_token(const char* ekey)
0574 {
0575 std::stringstream ss ;
0576
0577 char* ek = strdup(ekey) ;
0578 char* o = strstr(ek, "${" );
0579 char* c = strstr(ek, "}" );
0580 char* t = c ? c+1 : nullptr ;
0581
0582 if( o != ek )
0583 {
0584 *o = '\0' ;
0585 ss << ek ;
0586 }
0587
0588 o += 2 ;
0589 *c = '\0' ;
0590
0591 char* ov = getenv(o) ;
0592 ss << ( ov ? ov : o ) << t ;
0593 std::string str = ss.str();
0594
0595 return strdup(str.c_str()) ;
0596 }
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609 inline char* ssys::_tokenized_getenv(const char* ekey)
0610 {
0611 std::string str = _replace_envvar_token(ekey) ;
0612 char* k = strdup(str.c_str()) ;
0613 char* kv = getenv(k) ;
0614 return kv ? kv : k ;
0615 }
0616
0617
0618
0619
0620 template<typename T>
0621 inline T ssys::parse(const char* str_)
0622 {
0623 std::string str(str_);
0624 std::istringstream iss(str);
0625 T tval ;
0626 iss >> tval ;
0627 return tval ;
0628 }
0629
0630
0631
0632
0633 template<>
0634 inline std::string ssys::parse(const char* str_)
0635 {
0636 std::string str( str_ ? str_ : "" ) ;
0637 return str ;
0638 }
0639
0640 template int ssys::parse(const char*);
0641 template unsigned ssys::parse(const char*);
0642 template float ssys::parse(const char*);
0643 template double ssys::parse(const char*);
0644
0645
0646
0647 template<typename T>
0648 inline T ssys::getenv_(const char* ekey, T fallback)
0649 {
0650 char* v = getenv(ekey);
0651 int len = v ? strlen(v) : 0 ;
0652 return len == 0 ? fallback : parse<T>(v) ;
0653 }
0654
0655 template int ssys::getenv_(const char*, int );
0656 template unsigned ssys::getenv_(const char*, unsigned );
0657 template float ssys::getenv_(const char*, float );
0658 template double ssys::getenv_(const char*, double );
0659 template std::string ssys::getenv_(const char*, std::string );
0660
0661
0662
0663
0664
0665
0666
0667 template<typename T>
0668 void ssys::getenv_(std::vector<std::pair<std::string, T>>& kv, const std::vector<std::string>& kk )
0669 {
0670 typedef typename std::pair<std::string,T> KV ;
0671 for(int i=0 ; i < int(kk.size()) ; i++)
0672 {
0673 const char* k = kk[i].c_str() ;
0674 const char* v_ = _getenv(k) ;
0675 if(v_ == nullptr) continue ;
0676
0677 T v = parse<T>(v_) ;
0678 kv.push_back(KV(k,v)) ;
0679 }
0680 }
0681
0682 template<typename T>
0683 void ssys::getenv_(std::vector<std::pair<std::string, T>>& kv, const char* kk_ )
0684 {
0685 std::vector<std::string> kk ;
0686 std::stringstream ss(kk_) ;
0687 std::string line ;
0688 while (std::getline(ss, line))
0689 {
0690 if(line.empty()) continue ;
0691 line = std::regex_replace(line, std::regex(R"(^\s+|\s+$)"), "");
0692 if(line.empty()) continue ;
0693 kk.push_back(line);
0694 }
0695 getenv_(kv, kk );
0696 }
0697
0698
0699
0700 template<typename T>
0701 inline void ssys::fill_vec( std::vector<T>& vec, const char* line, char delim )
0702 {
0703 std::stringstream ss;
0704 ss.str(line);
0705 std::string s;
0706 while (std::getline(ss, s, delim))
0707 {
0708 if(delim == '\n' && sstr::IsWhitespace(s)) continue ;
0709 std::istringstream iss(s);
0710 T t ;
0711 iss >> t ;
0712 vec.push_back(t) ;
0713 }
0714 }
0715
0716 template void ssys::fill_vec( std::vector<int>& , const char*, char );
0717 template void ssys::fill_vec( std::vector<unsigned>& , const char*, char );
0718 template void ssys::fill_vec( std::vector<float>& , const char*, char );
0719 template void ssys::fill_vec( std::vector<double>& , const char*, char );
0720 template void ssys::fill_vec( std::vector<std::string>& , const char*, char );
0721
0722
0723
0724 template<typename T>
0725 inline void ssys::fill_evec(std::vector<T>& vec, const char* ekey, const char* fallback, char delim )
0726 {
0727 assert(fallback);
0728 char* line_ = getenv(ekey);
0729 if(line_ == nullptr && fallback == nullptr) return ;
0730 const char* line = line_ ? line_ : fallback ;
0731 fill_vec<T>( vec, line, delim );
0732 }
0733
0734 template void ssys::fill_evec( std::vector<int>& , const char*, const char*, char );
0735 template void ssys::fill_evec( std::vector<unsigned>& , const char*, const char*, char );
0736 template void ssys::fill_evec( std::vector<float>& , const char*, const char*, char );
0737 template void ssys::fill_evec( std::vector<double>& , const char*, const char*, char );
0738 template void ssys::fill_evec( std::vector<std::string>& , const char*, const char*, char );
0739
0740
0741 template<typename T>
0742 inline std::vector<T>* ssys::make_vec(const char* line, char delim )
0743 {
0744 if(line == nullptr) return nullptr ;
0745 std::vector<T>* vec = new std::vector<T>() ;
0746 fill_vec<T>( *vec, line, delim );
0747 return vec ;
0748 }
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758
0759
0760
0761 template<typename T>
0762 inline std::vector<T>* ssys::getenv_vec(const char* ekey, const char* fallback, char delim )
0763 {
0764 char* line = getenv(ekey);
0765 bool valid = line && strlen(line) > 0 ;
0766 return make_vec<T>( valid ? line : fallback, delim );
0767 }
0768
0769
0770 template std::vector<int>* ssys::getenv_vec(const char*, const char*, char );
0771 template std::vector<unsigned>* ssys::getenv_vec(const char*, const char*, char );
0772 template std::vector<float>* ssys::getenv_vec(const char*, const char*, char );
0773 template std::vector<double>* ssys::getenv_vec(const char*, const char*, char );
0774 template std::vector<std::string>* ssys::getenv_vec(const char*, const char*, char );
0775
0776
0777 inline std::vector<int>* ssys::getenvintvec(const char* envkey, char delim)
0778 {
0779 return getenv_vec<int>(envkey, nullptr, delim);
0780 }
0781
0782 inline void ssys::getenvintvec( const char* ekey, std::vector<int>& vec, char delim, const char* fallback )
0783 {
0784 fill_evec<int>( vec, ekey, fallback, delim );
0785 }
0786
0787
0788
0789
0790 inline std::vector<float>* ssys::getenvfloatvec(const char* envkey, const char* fallback, char delim)
0791 {
0792 return getenv_vec<float>(envkey, fallback, delim);
0793 }
0794
0795
0796
0797
0798
0799
0800 template<typename T>
0801 inline std::string ssys::desc_vec( const std::vector<T>* vec, unsigned edgeitems )
0802 {
0803 unsigned size = vec ? vec->size() : 0 ;
0804
0805 std::stringstream ss ;
0806 ss << "(" ;
0807 for(unsigned i=0 ; i < size ; i++) if(i < edgeitems || i > size - edgeitems ) ss << (*vec)[i] << " " ;
0808 ss << ")" ;
0809
0810 std::string s = ss.str();
0811 return s;
0812 }
0813
0814
0815 template std::string ssys::desc_vec(const std::vector<int>* , unsigned ) ;
0816 template std::string ssys::desc_vec(const std::vector<unsigned>* , unsigned ) ;
0817 template std::string ssys::desc_vec(const std::vector<float>* , unsigned ) ;
0818 template std::string ssys::desc_vec(const std::vector<double>* , unsigned ) ;
0819 template std::string ssys::desc_vec(const std::vector<std::string>* , unsigned ) ;
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832 inline int ssys::idx_listed( const std::vector<std::string>* nn, const char* n )
0833 {
0834 return nn ? std::distance( nn->begin(), std::find( nn->begin(), nn->end(), n ) ) : -1 ;
0835 }
0836
0837 inline bool ssys::is_listed( const std::vector<std::string>* nn, const char* n )
0838 {
0839 int sz = nn ? nn->size() : 0 ;
0840 int idx = idx_listed(nn, n) ;
0841 return idx > -1 && idx < sz ;
0842 }
0843
0844
0845
0846
0847
0848
0849
0850
0851
0852
0853
0854
0855 inline int ssys::listed_count( std::vector<int>* ncount, const std::vector<std::string>* nn, const char* n )
0856 {
0857 if(nn == nullptr || ncount == nullptr) return -1 ;
0858 int sz = nn->size() ;
0859 ncount->resize(sz);
0860 int idx = idx_listed(nn,n) ;
0861 if(idx >= sz) return -1 ;
0862 int count = ncount->at(idx) ;
0863 (*ncount)[idx] += 1 ;
0864 return count ;
0865 }
0866
0867
0868 inline std::string ssys::desc_listed_count( const std::vector<int>* ncount, const std::vector<std::string>* nn )
0869 {
0870 int ncount_sz = ncount ? int(ncount->size()) : -1 ;
0871 int nn_sz = nn ? int(nn->size()) : -1 ;
0872
0873 std::stringstream ss ;
0874 ss << "ssys::desc_listed_count"
0875 << " ncount_sz " << ncount_sz
0876 << " nn_sz " << nn_sz
0877 << std::endl
0878 ;
0879
0880 if( ncount_sz == nn_sz && nn_sz > -1 )
0881 {
0882 for(int i=0 ; i < nn_sz ; i++ ) ss << std::setw(3) << i << " : " << (*ncount)[i] << " : " << (*nn)[i] << std::endl ;
0883 }
0884 std::string str = ss.str();
0885 return str ;
0886 }
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901 inline bool ssys::is_remote_session()
0902 {
0903 char* ssh_client = getenv("SSH_CLIENT");
0904 char* ssh_tty = getenv("SSH_TTY");
0905 bool is_remote = ssh_client != nullptr || ssh_tty != nullptr ;
0906 return is_remote ;
0907 }
0908
0909
0910
0911 inline const char* ssys::username()
0912 {
0913 #ifdef _MSC_VER
0914 const char* user = ssys::getenvvar("USERNAME", "no-USERNAME") ;
0915 #else
0916 const char* user = ssys::getenvvar("USER", "no-USER" ) ;
0917 #endif
0918 return user ? user : "ssys-username-undefined" ;
0919 }
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932 inline void ssys::Dump(const char* msg)
0933 {
0934 static int COUNT = -1 ;
0935 COUNT++ ;
0936 std::cout << std::setw(3) << COUNT << "[" << std::setw(20) << "std::cout" << "] " << msg << std::endl;
0937 std::cerr << std::setw(3) << COUNT << "[" << std::setw(20) << "std::cerr" << "] " << msg << std::endl;
0938 printf("%3d[%20s] %s \n", COUNT, "printf", msg );
0939 std::printf("%3d[%20s] %s \n", COUNT, "std::printf", msg );
0940 std::cerr << std::endl ;
0941 }
0942
0943
0944 inline int ssys::run(const char* cmd)
0945 {
0946 int rc_raw = system(cmd);
0947 int rc = WEXITSTATUS(rc_raw) ;
0948
0949 std::cout
0950 << "ssys::run "
0951 << ( cmd ? cmd : "-" )
0952 << " rc_raw : " << rc_raw
0953 << " rc : " << rc
0954 << std::endl
0955 ;
0956
0957 if(rc != 0) std::cout
0958 << "ssys::run"
0959 << " PATH ENVVAR MISCONFIGURED ? "
0960 << std::endl
0961 ;
0962 return rc ;
0963 }
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983 inline int ssys::setenvvar( const char* ekey, const char* value, bool overwrite, char special_empty_token)
0984 {
0985 std::stringstream ss ;
0986 ss << ekey << "=" ;
0987
0988 if(value)
0989 {
0990 if(special_empty_token != '\0' && strlen(value) == 1 && value[0] == special_empty_token)
0991 {
0992 ss << "" ;
0993 }
0994 else
0995 {
0996 ss << value ;
0997 }
0998 }
0999
1000 std::string ekv = ss.str();
1001 const char* prior = getenv(ekey) ;
1002
1003 char* ekv_ = const_cast<char*>(strdup(ekv.c_str()));
1004
1005 int rc = ( overwrite || !prior ) ? putenv(ekv_) : 0 ;
1006
1007 const char* after = getenv(ekey) ;
1008
1009 if(VERBOSE) std::cerr
1010 << "ssys::setenvvar"
1011 << " ekey " << ekey
1012 << " ekv " << ekv
1013 << " overwrite " << overwrite
1014 << " prior " << ( prior ? prior : "NULL" )
1015 << " value " << ( value ? value : "NULL" )
1016 << " after " << ( after ? after : "NULL" )
1017 << " rc " << rc
1018 << std::endl
1019 ;
1020
1021
1022 return rc ;
1023 }
1024
1025
1026 inline int ssys::setenvmap( const std::map<std::string, std::string>& env, bool overwrite, char special_empty_token )
1027 {
1028 typedef std::map<std::string, std::string> MSS ;
1029 for(MSS::const_iterator it=env.begin() ; it != env.end() ; it++)
1030 {
1031 const std::string& key = it->first ;
1032 const std::string& val = it->second ;
1033 setenvvar(key.c_str(), val.c_str(), overwrite, special_empty_token );
1034 }
1035 return 0 ;
1036 }
1037
1038
1039 template<typename ... Args>
1040 inline int ssys::setenvctx( Args ... args_ )
1041 {
1042 std::vector<std::string> args = {args_...};
1043 std::vector<std::string> elem ;
1044
1045 for(unsigned i=0 ; i < args.size() ; i++)
1046 {
1047 const std::string& arg = args[i] ;
1048 if(!arg.empty()) elem.push_back(arg);
1049 }
1050
1051 unsigned num_elem = elem.size() ;
1052 assert( num_elem % 2 == 0 );
1053
1054 bool overwrite = true ;
1055 char special_empty_token = '\0' ;
1056
1057 for(unsigned i=0 ; i < num_elem/2 ; i++)
1058 {
1059 const std::string& key = elem[2*i+0] ;
1060 const std::string& val = elem[2*i+1] ;
1061 setenvvar(key.c_str(), val.c_str(), overwrite, special_empty_token );
1062 }
1063 return 0 ;
1064 }
1065
1066
1067 template int ssys::setenvctx(
1068 const char*, const char* );
1069 template int ssys::setenvctx(
1070 const char*, const char*,
1071 const char*, const char* );
1072 template int ssys::setenvctx(
1073 const char*, const char*,
1074 const char*, const char*,
1075 const char*, const char* );
1076 template int ssys::setenvctx(
1077 const char*, const char*,
1078 const char*, const char*,
1079 const char*, const char*,
1080 const char*, const char* );
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099 inline std::string ssys::Desc()
1100 {
1101 std::stringstream ss ;
1102 ss << "ssys::Desc"
1103 << std::endl
1104 #ifdef CONFIG_Debug
1105 << "CONFIG_Debug"
1106 #else
1107 << "NOT:CONFIG_Debug"
1108 #endif
1109 << std::endl
1110 #ifdef CONFIG_Release
1111 << "CONFIG_Release"
1112 #else
1113 << "NOT:CONFIG_Release"
1114 #endif
1115 << std::endl
1116 #ifdef CONFIG_RelWithDebInfo
1117 << "CONFIG_RelWithDebInfo"
1118 #else
1119 << "NOT:CONFIG_RelWithDebInfo"
1120 #endif
1121 << std::endl
1122 #ifdef CONFIG_MinSizeRel
1123 << "CONFIG_MinSizeRel"
1124 #else
1125 << "NOT:CONFIG_MinSizeRel"
1126 #endif
1127 << std::endl
1128 #ifdef PRODUCTION
1129 << "PRODUCTION"
1130 #else
1131 << "NOT:PRODUCTION"
1132 #endif
1133 << std::endl
1134 #ifdef WITH_CHILD
1135 << "WITH_CHILD"
1136 #else
1137 << "NOT:WITH_CHILD"
1138 #endif
1139 << std::endl
1140 #ifdef WITH_CUSTOM4
1141 << "WITH_CUSTOM4"
1142 #else
1143 << "NOT:WITH_CUSTOM4"
1144 #endif
1145 << std::endl
1146 #ifdef PLOG_LOCAL
1147 << "PLOG_LOCAL"
1148 #else
1149 << "NOT:PLOG_LOCAL"
1150 #endif
1151 << std::endl
1152 #ifdef DEBUG_PIDX
1153 << "DEBUG_PIDX"
1154 #else
1155 << "NOT:DEBUG_PIDX"
1156 #endif
1157 << std::endl
1158 #ifdef DEBUG_TAG
1159 << "DEBUG_TAG"
1160 #else
1161 << "NOT:DEBUG_TAG"
1162 #endif
1163 << std::endl
1164 ;
1165 std::string str = ss.str() ;
1166 return str ;
1167 }
1168
1169 inline std::string ssys::PWD()
1170 {
1171 return getenvvar("PWD");
1172 }
1173
1174
1175 #ifdef _MSC_VER
1176 #else
1177 #include <unistd.h>
1178 extern char **environ;
1179 #endif
1180
1181
1182 inline void ssys::getenv_with_prefix(std::vector<std::pair<std::string,std::string>>& kvs, const char* prefix)
1183 {
1184 #ifdef _MSC_VER
1185 #else
1186 int i=0 ;
1187 char delim='=' ;
1188 while(environ[i])
1189 {
1190 std::string kv = environ[i++] ;
1191 size_t pos = kv.find(delim);
1192 if( pos == std::string::npos ) continue ;
1193 std::string k = kv.substr(0, pos);
1194 std::string v = kv.substr(pos+1);
1195 bool match_prefix = prefix ? sstr::StartsWith( k.c_str(), prefix ) : true ;
1196
1197 if(!match_prefix) continue ;
1198 kvs.push_back( std::pair<std::string,std::string>( k, v ) );
1199 }
1200 #endif
1201 }
1202
1203