cmdline: simplify string splitting

This commit is contained in:
Robert Swiecki 2018-02-11 14:56:30 +01:00
parent 7b9178f5d7
commit f1a6b08962
6 changed files with 89 additions and 86 deletions

View File

@ -43,6 +43,8 @@
#include <unistd.h>
#include <memory>
#include <string>
#include <vector>
#include "caps.h"
#include "config.h"
@ -293,29 +295,16 @@ uint64_t parseRLimit(int res, const char* optarg, unsigned long mul) {
return val;
}
/* findSpecDestination mutates spec (source:dest) to have a null byte instead
* of ':' in between source and dest, then returns a pointer to the dest
* string. */
static char* cmdlineSplitStrByColon(char* spec) {
if (spec == NULL) {
return NULL;
static std::string argByColon(const char* str, size_t pos) {
if (!str) {
return "";
}
char* dest = spec;
while (*dest != ':' && *dest != '\0') {
dest++;
}
switch (*dest) {
case ':':
*dest = '\0';
return dest + 1;
case '\0':
return NULL;
default:
LOG_F("Impossible condition in cmdlineSplitStrByColon()");
return NULL;
std::vector<std::string> vec;
util::strSplit(str, &vec, ':');
if (pos > vec.size()) {
return "";
}
return vec[pos];
}
std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
@ -568,66 +557,67 @@ std::unique_ptr<nsjconf_t> parseArgs(int argc, char* argv[]) {
nsjconf->envs.push_back(optarg);
break;
case 'u': {
char* i_id = optarg;
char* o_id = cmdlineSplitStrByColon(i_id);
char* cnt = cmdlineSplitStrByColon(o_id);
size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (user::parseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
false /* is_newidmap */) == false) {
std::string i_id = argByColon(optarg, 0);
std::string o_id = argByColon(optarg, 1);
std::string cnt = argByColon(optarg, 2);
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ false,
/* is_newidmap= */ false)) {
return nullptr;
}
} break;
case 'g': {
char* i_id = optarg;
char* o_id = cmdlineSplitStrByColon(i_id);
char* cnt = cmdlineSplitStrByColon(o_id);
size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (user::parseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
false /* is_newidmap */) == false) {
std::string i_id = argByColon(optarg, 0);
std::string o_id = argByColon(optarg, 1);
std::string cnt = argByColon(optarg, 2);
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ true,
/* is_newidmap= */ false)) {
return nullptr;
}
} break;
case 'U': {
char* i_id = optarg;
char* o_id = cmdlineSplitStrByColon(i_id);
char* cnt = cmdlineSplitStrByColon(o_id);
size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (user::parseId(nsjconf.get(), i_id, o_id, count, false /* is_gid */,
true /* is_newidmap */) == false) {
std::string i_id = argByColon(optarg, 0);
std::string o_id = argByColon(optarg, 1);
std::string cnt = argByColon(optarg, 2);
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ false,
/* is_newidmap= */ true)) {
return nullptr;
}
} break;
case 'G': {
char* i_id = optarg;
char* o_id = cmdlineSplitStrByColon(i_id);
char* cnt = cmdlineSplitStrByColon(o_id);
size_t count =
(cnt == NULL || strlen(cnt) == 0) ? 1U : (size_t)strtoull(cnt, NULL, 0);
if (user::parseId(nsjconf.get(), i_id, o_id, count, true /* is_gid */,
true /* is_newidmap */) == false) {
std::string i_id = argByColon(optarg, 0);
std::string o_id = argByColon(optarg, 1);
std::string cnt = argByColon(optarg, 2);
size_t count = std::strtoul(cnt.c_str(), nullptr, 0);
if (!user::parseId(nsjconf.get(), i_id, o_id, count, /* is_gid= */ true,
/* is_newidmap= */ true)) {
return nullptr;
}
} break;
case 'R': {
const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mnt::addMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
/* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY,
std::string src = argByColon(optarg, 0);
std::string dst = argByColon(optarg, 1);
if (dst.empty()) {
dst = src;
}
if (!mnt::addMountPtTail(nsjconf.get(), src.c_str(), dst.c_str(),
/* fs_type= */ "", /* options= */ "",
MS_BIND | MS_REC | MS_PRIVATE | MS_RDONLY,
/* isDir= */ mnt::NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL,
NULL, 0, /* is_symlink= */ false)) {
return nullptr;
}
}; break;
case 'B': {
const char* dst = cmdlineSplitStrByColon(optarg);
dst = dst ? dst : optarg;
if (!mnt::addMountPtTail(nsjconf.get(), /* src= */ optarg, dst,
/* fs_type= */ "",
/* options= */ "", MS_BIND | MS_REC | MS_PRIVATE,
std::string src = argByColon(optarg, 0);
std::string dst = argByColon(optarg, 1);
if (dst.empty()) {
dst = src;
}
if (!mnt::addMountPtTail(nsjconf.get(), src.c_str(), dst.c_str(),
/* fs_type= */ "", /* options= */ "", MS_BIND | MS_REC | MS_PRIVATE,
/* isDir= */ mnt::NS_DIR_MAYBE, /* mandatory= */ true, NULL, NULL,
NULL, 0, /* is_symlink= */ false)) {
return nullptr;

View File

@ -45,8 +45,6 @@
namespace config {
#define VAL_IF_SET_OR_NULL(njc, val) (njc.has_##val() ? njc.val().c_str() : NULL)
static uint64_t configRLimit(
int res, const nsjail::RLimit& rl, const uint64_t val, unsigned long mul = 1UL) {
if (rl == nsjail::RLimit::VALUE) {
@ -186,16 +184,14 @@ static bool configParseInternal(nsjconf_t* nsjconf, const nsjail::NsJailConfig&
nsjconf->clone_newcgroup = njc.clone_newcgroup();
for (ssize_t i = 0; i < njc.uidmap_size(); i++) {
if (!user::parseId(nsjconf, VAL_IF_SET_OR_NULL(njc.uidmap(i), inside_id),
VAL_IF_SET_OR_NULL(njc.uidmap(i), outside_id), njc.uidmap(i).count(),
false /* is_gid */, njc.uidmap(i).use_newidmap())) {
if (!user::parseId(nsjconf, njc.uidmap(i).inside_id(), njc.uidmap(i).outside_id(),
njc.uidmap(i).count(), false /* is_gid */, njc.uidmap(i).use_newidmap())) {
return false;
}
}
for (ssize_t i = 0; i < njc.gidmap_size(); i++) {
if (!user::parseId(nsjconf, VAL_IF_SET_OR_NULL(njc.gidmap(i), inside_id),
VAL_IF_SET_OR_NULL(njc.gidmap(i), outside_id), njc.gidmap(i).count(),
true /* is_gid */, njc.gidmap(i).use_newidmap())) {
if (!user::parseId(nsjconf, njc.gidmap(i).inside_id(), njc.gidmap(i).outside_id(),
njc.gidmap(i).count(), true /* is_gid */, njc.gidmap(i).use_newidmap())) {
return false;
}
}

36
user.cc
View File

@ -265,59 +265,63 @@ bool initNsFromChild(nsjconf_t* nsjconf) {
return true;
}
static uid_t parseUid(const char* id) {
if (id == NULL || strlen(id) == 0) {
static uid_t parseUid(const std::string& id) {
if (id.empty()) {
return getuid();
}
struct passwd* pw = getpwnam(id);
struct passwd* pw = getpwnam(id.c_str());
if (pw != NULL) {
return pw->pw_uid;
}
if (util::isANumber(id)) {
return (uid_t)strtoull(id, NULL, 0);
if (util::isANumber(id.c_str())) {
return (uid_t)strtoull(id.c_str(), NULL, 0);
}
return (uid_t)-1;
}
static gid_t parseGid(const char* id) {
if (id == NULL || strlen(id) == 0) {
static gid_t parseGid(const std::string& id) {
if (id.empty()) {
return getgid();
}
struct group* gr = getgrnam(id);
struct group* gr = getgrnam(id.c_str());
if (gr != NULL) {
return gr->gr_gid;
}
if (util::isANumber(id)) {
return (gid_t)strtoull(id, NULL, 0);
if (util::isANumber(id.c_str())) {
return (gid_t)strtoull(id.c_str(), NULL, 0);
}
return (gid_t)-1;
}
bool parseId(nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt, bool is_gid,
bool is_newidmap) {
bool parseId(nsjconf_t* nsjconf, const std::string& i_id, const std::string& o_id, size_t cnt,
bool is_gid, bool is_newidmap) {
if (cnt < 1) {
cnt = 1;
}
uid_t inside_id;
uid_t outside_id;
if (is_gid) {
inside_id = parseGid(i_id);
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as GID", i_id);
LOG_W("Cannot parse '%s' as GID", i_id.c_str());
return false;
}
outside_id = parseGid(o_id);
if (outside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as GID", o_id);
LOG_W("Cannot parse '%s' as GID", o_id.c_str());
return false;
}
} else {
inside_id = parseUid(i_id);
if (inside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as UID", i_id);
LOG_W("Cannot parse '%s' as UID", i_id.c_str());
return false;
}
outside_id = parseUid(o_id);
if (outside_id == (uid_t)-1) {
LOG_W("Cannot parse '%s' as UID", o_id);
LOG_W("Cannot parse '%s' as UID", o_id.c_str());
return false;
}
}

7
user.h
View File

@ -24,15 +24,16 @@
#include <stdbool.h>
#include <string>
#include "nsjail.h"
namespace user {
bool initNsFromParent(nsjconf_t* nsjconf, pid_t pid);
bool initNsFromChild(nsjconf_t* nsjconf);
bool parseId(nsjconf_t* nsjconf, const char* i_id, const char* o_id, size_t cnt, bool is_gid,
bool is_newidmap);
bool parseId(nsjconf_t* nsjconf, const std::string& i_id, const std::string& o_id, size_t cnt,
bool is_gid, bool is_newidmap);
} // namespace user

10
util.cc
View File

@ -40,7 +40,9 @@
#include <time.h>
#include <unistd.h>
#include <sstream>
#include <string>
#include <vector>
#include "logs.h"
#include "macros.h"
@ -279,4 +281,12 @@ const std::string timeToStr(time_t t) {
return timestr;
}
void strSplit(const std::string str, std::vector<std::string>* vec, char delim) {
std::string word;
std::istringstream stream(str);
for (std::string word; std::getline(stream, word, delim);) {
vec->push_back(word);
}
}
} // namespace util

2
util.h
View File

@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string>
#include <vector>
#include "nsjail.h"
@ -42,6 +43,7 @@ bool isANumber(const char* s);
uint64_t rnd64(void);
const std::string sigName(int signo);
const std::string timeToStr(time_t t);
void strSplit(const std::string str, std::vector<std::string>* vec, char delim);
} // namespace util