This commit is contained in:
Jean-Francois Dockes 2016-03-22 13:50:49 +01:00
parent 90afc535a4
commit ae2962a41c
6 changed files with 785 additions and 703 deletions

View file

@ -113,7 +113,7 @@ public:
sigemptyset(&m_blkcld);
}
// Child process code
inline void dochild(const std::string &cmd, const char **argv,
inline void dochild(const std::string& cmd, const char **argv,
const char **envv, bool has_input, bool has_output);
};
bool ExecCmd::Internal::o_useVfork = false;
@ -121,8 +121,9 @@ bool ExecCmd::Internal::o_useVfork = false;
ExecCmd::ExecCmd(int)
{
m = new Internal();
if (m)
if (m) {
m->reset();
}
}
void ExecCmd::setAdvise(ExecCmdAdvise *adv)
{
@ -134,10 +135,11 @@ void ExecCmd::setProvide(ExecCmdProvide *p)
}
void ExecCmd::setTimeout(int mS)
{
if (mS > 30)
if (mS > 30) {
m->m_timeoutMs = mS;
}
}
void ExecCmd::setStderr(const std::string &stderrFile)
void ExecCmd::setStderr(const std::string& stderrFile)
{
m->m_stderrFile = stderrFile;
}
@ -158,9 +160,10 @@ void ExecCmd::zapChild()
bool ExecCmd::requestChildExit()
{
if (m->m_pid > 0) {
if (kill(m->m_pid, SIGTERM) == 0)
if (kill(m->m_pid, SIGTERM) == 0) {
return true;
}
}
return false;
}
@ -182,8 +185,9 @@ static bool exec_is_there(const char *candidate)
bool ExecCmd::which(const string& cmd, string& exepath, const char* path)
{
if (cmd.empty())
if (cmd.empty()) {
return false;
}
if (cmd[0] == '/') {
if (exec_is_there(cmd.c_str())) {
exepath = cmd;
@ -199,14 +203,16 @@ bool ExecCmd::which(const string& cmd, string& exepath, const char* path)
} else {
pp = getenv("PATH");
}
if (pp == 0)
if (pp == 0) {
return false;
}
vector<string> pels;
stringToTokens(pp, pels, ":");
for (vector<string>::iterator it = pels.begin(); it != pels.end(); it++) {
if (it->empty())
if (it->empty()) {
*it = ".";
}
string candidate = (it->empty() ? string(".") : *it) + "/" + cmd;
if (exec_is_there(candidate.c_str())) {
exepath = candidate;
@ -227,12 +233,12 @@ void ExecCmd::useVfork(bool on)
Internal::o_useVfork = on;
}
void ExecCmd::putenv(const string &ea)
void ExecCmd::putenv(const string& ea)
{
m->m_env.push_back(ea);
}
void ExecCmd::putenv(const string &name, const string& value)
void ExecCmd::putenv(const string& name, const string& value)
{
string ea = name + "=" + value;
putenv(ea);
@ -258,19 +264,24 @@ public:
m_active = false;
}
~ExecCmdRsrc() {
if (!m_active || !m_parent)
if (!m_active || !m_parent) {
return;
}
LOGDEB1(("~ExecCmdRsrc: working. mypid: %d\n", (int)getpid()));
// Better to close the descs first in case the child is waiting in read
if (m_parent->m_pipein[0] >= 0)
if (m_parent->m_pipein[0] >= 0) {
close(m_parent->m_pipein[0]);
if (m_parent->m_pipein[1] >= 0)
}
if (m_parent->m_pipein[1] >= 0) {
close(m_parent->m_pipein[1]);
if (m_parent->m_pipeout[0] >= 0)
}
if (m_parent->m_pipeout[0] >= 0) {
close(m_parent->m_pipeout[0]);
if (m_parent->m_pipeout[1] >= 0)
}
if (m_parent->m_pipeout[1] >= 0) {
close(m_parent->m_pipeout[1]);
}
// It's apparently possible for m_pid to be > 0 and getpgid to fail. In
// this case, we have to conclude that the child process does
@ -285,8 +296,9 @@ public:
msleep(i == 0 ? 5 : (i == 1 ? 100 : 2000));
int status;
(void)waitpid(m_parent->m_pid, &status, WNOHANG);
if (kill(m_parent->m_pid, 0) != 0)
if (kill(m_parent->m_pid, 0) != 0) {
break;
}
if (i == 2) {
LOGDEB(("ExecCmd: killpg(%d, SIGKILL)\n", grp));
killpg(grp, SIGKILL);
@ -311,8 +323,9 @@ private:
ExecCmd::~ExecCmd()
{
ExecCmdRsrc(this->m);
if (m)
if (m) {
delete m;
}
}
// In child process. Set up pipes and exec command.
@ -328,7 +341,7 @@ ExecCmd::~ExecCmd()
// If one of the calls block, the problem manifests itself by 20mn
// (filter timeout) of looping on "ExecCmd::doexec: selectloop
// returned 1', because the father is waiting on the read descriptor
inline void ExecCmd::Internal::dochild(const string &cmd, const char **argv,
inline void ExecCmd::Internal::dochild(const string& cmd, const char **argv,
const char **envv,
bool has_input, bool has_output)
{
@ -411,9 +424,9 @@ inline void ExecCmd::Internal::dochild(const string &cmd, const char **argv,
}
// Do we need to redirect stderr ?
if (!m_stderrFile.empty()) {
int fd = open(m_stderrFile.c_str(), O_WRONLY|O_CREAT
int fd = open(m_stderrFile.c_str(), O_WRONLY | O_CREAT
#ifdef O_APPEND
|O_APPEND
| O_APPEND
#endif
, 0600);
if (fd < 0) {
@ -443,10 +456,11 @@ void ExecCmd::setrlimit_as(int mbytes)
m->m_rlimit_as_mbytes = mbytes;
}
int ExecCmd::startExec(const string &cmd, const vector<string>& args,
int ExecCmd::startExec(const string& cmd, const vector<string>& args,
bool has_input, bool has_output)
{
{ // Debug and logging
{
// Debug and logging
string command = cmd + " ";
for (vector<string>::const_iterator it = args.begin();
it != args.end(); it++) {
@ -478,7 +492,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Allocate arg vector (2 more for arg0 + final 0)
typedef const char *Ccharp;
Ccharp *argv;
argv = (Ccharp *)malloc((args.size()+2) * sizeof(char *));
argv = (Ccharp *)malloc((args.size() + 2) * sizeof(char *));
if (argv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
return -1;
@ -495,8 +509,9 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
Ccharp *envv;
int envsize;
for (envsize = 0; ; envsize++)
if (environ[envsize] == 0)
if (environ[envsize] == 0) {
break;
}
envv = (Ccharp *)malloc((envsize + m->m_env.size() + 2) * sizeof(char *));
if (envv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
@ -504,8 +519,9 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
return -1;
}
int eidx;
for (eidx = 0; eidx < envsize; eidx++)
for (eidx = 0; eidx < envsize; eidx++) {
envv[eidx] = environ[eidx];
}
for (vector<string>::const_iterator it = m->m_env.begin();
it != m->m_env.end(); it++) {
envv[eidx++] = it->c_str();
@ -526,7 +542,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Note that posix_spawn provides no way to setrlimit() the child.
{
posix_spawnattr_t attrs;
posix_spawnattr_init (&attrs);
posix_spawnattr_init(&attrs);
short flags;
posix_spawnattr_getflags(&attrs, &flags);
@ -537,7 +553,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
sigset_t sset;
sigemptyset(&sset);
posix_spawnattr_setsigmask (&attrs, &sset);
posix_spawnattr_setsigmask(&attrs, &sset);
flags |= POSIX_SPAWN_SETSIGMASK;
sigemptyset(&sset);
@ -567,7 +583,7 @@ int ExecCmd::startExec(const string &cmd, const vector<string>& args,
// Do we need to redirect stderr ?
if (!m->m_stderrFile.empty()) {
int oflags = O_WRONLY|O_CREAT;
int oflags = O_WRONLY | O_CREAT;
#ifdef O_APPEND
oflags |= O_APPEND;
#endif
@ -670,10 +686,10 @@ public:
m_cmd->m_pipein[1] = -1;
m_cmd->m_tocmd.reset();
}
virtual int data(NetconData *con, Netcon::Event reason)
{
if (!m_input)
virtual int data(NetconData *con, Netcon::Event reason) {
if (!m_input) {
return -1;
}
LOGDEB1(("ExecWriter: input m_cnt %d input length %d\n", m_cnt,
m_input->length()));
if (m_cnt >= m_input->length()) {
@ -715,10 +731,9 @@ private:
class ExecReader : public NetconWorker {
public:
ExecReader(string *output, ExecCmdAdvise *advise)
: m_output(output), m_advise(advise)
{}
virtual int data(NetconData *con, Netcon::Event reason)
{
: m_output(output), m_advise(advise) {
}
virtual int data(NetconData *con, Netcon::Event reason) {
char buf[8192];
int n = con->receive(buf, 8192);
LOGDEB1(("ExecReader: got %d from command\n", n));
@ -726,8 +741,9 @@ public:
LOGERR(("ExecCmd::doexec: receive failed. errno %d\n", errno));
} else if (n > 0) {
m_output->append(buf, n);
if (m_advise)
if (m_advise) {
m_advise->newData(n);
}
} // else n == 0, just return
return n;
}
@ -737,7 +753,7 @@ private:
};
int ExecCmd::doexec(const string &cmd, const vector<string>& args,
int ExecCmd::doexec(const string& cmd, const vector<string>& args,
const string *input, string *output)
{
@ -781,8 +797,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
myloop.setperiodichandler(0, 0, m->m_timeoutMs);
while ((ret = myloop.doLoop()) > 0) {
LOGDEB(("ExecCmd::doexec: selectloop returned %d\n", ret));
if (m->m_advise)
if (m->m_advise) {
m->m_advise->newData(0);
}
if (m->m_killRequest) {
LOGINFO(("ExecCmd::doexec: cancel request\n"));
break;
@ -790,8 +807,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
}
LOGDEB0(("ExecCmd::doexec: selectloop returned %d\n", ret));
// Check for interrupt request: we won't want to waitpid()
if (m->m_advise)
if (m->m_advise) {
m->m_advise->newData(0);
}
// The netcons don't take ownership of the fds: we have to close them
// (have to do it before wait, this may be the signal the child is
@ -810,8 +828,9 @@ int ExecCmd::doexec(const string &cmd, const vector<string>& args,
e.inactivate();
int ret1 = ExecCmd::wait();
if (ret)
if (ret) {
return -1;
}
return ret1;
}
@ -824,8 +843,9 @@ int ExecCmd::send(const string& data)
}
unsigned int nwritten = 0;
while (nwritten < data.length()) {
if (m->m_killRequest)
if (m->m_killRequest) {
break;
}
int n = con->send(data.c_str() + nwritten, data.length() - nwritten);
if (n < 0) {
LOGERR(("ExecCmd::send: send failed\n"));
@ -873,8 +893,9 @@ int ExecCmd::getline(string& data)
const int BS = 1024;
char buf[BS];
int timeosecs = m->m_timeoutMs / 1000;
if (timeosecs == 0)
if (timeosecs == 0) {
timeosecs = 1;
}
// Note that we only go once through here, except in case of
// timeout, which is why I think that the goto is more expressive
@ -884,8 +905,9 @@ again:
if (n < 0) {
if (con->timedout()) {
LOGDEB(("ExecCmd::getline: timeout\n"));
if (m->m_advise)
if (m->m_advise) {
m->m_advise->newData(0);
}
goto again;
}
LOGERR(("ExecCmd::getline: error\n"));
@ -1006,15 +1028,16 @@ void ReExec::init(int argc, char *args[])
}
m_cfd = open(".", 0);
char *cd = getcwd(0, 0);
if (cd)
if (cd) {
m_curdir = cd;
}
free(cd);
}
void ReExec::insertArgs(const vector<string>& args, int idx)
{
vector<string>::iterator it, cit;
unsigned int cmpoffset = (unsigned int)-1;
unsigned int cmpoffset = (unsigned int) - 1;
if (idx == -1 || string::size_type(idx) >= m_argv.size()) {
it = m_argv.end();
@ -1029,7 +1052,7 @@ void ReExec::insertArgs(const vector<string>& args, int idx)
}
// Check that the option is not already there
if (cmpoffset != (unsigned int)-1) {
if (cmpoffset != (unsigned int) - 1) {
bool allsame = true;
for (unsigned int i = 0; i < args.size(); i++) {
if (m_argv[cmpoffset + i] != args[i]) {
@ -1037,9 +1060,10 @@ void ReExec::insertArgs(const vector<string>& args, int idx)
break;
}
}
if (allsame)
if (allsame) {
return;
}
}
m_argv.insert(it, args.begin(), args.end());
}
@ -1048,9 +1072,10 @@ void ReExec::removeArg(const string& arg)
{
for (vector<string>::iterator it = m_argv.begin();
it != m_argv.end(); it++) {
if (*it == arg)
if (*it == arg) {
it = m_argv.erase(it);
}
}
}
// Reexecute myself, as close as possible to the initial exec
@ -1059,10 +1084,10 @@ void ReExec::reexec()
#if 0
char *cwd;
cwd = getcwd(0,0);
cwd = getcwd(0, 0);
FILE *fp = stdout; //fopen("/tmp/exectrace", "w");
if (fp) {
fprintf(fp, "reexec: pwd: [%s] args: ", cwd?cwd:"getcwd failed");
fprintf(fp, "reexec: pwd: [%s] args: ", cwd ? cwd : "getcwd failed");
for (vector<string>::const_iterator it = m_argv.begin();
it != m_argv.end(); it++) {
fprintf(fp, "[%s] ", it->c_str());
@ -1091,7 +1116,7 @@ void ReExec::reexec()
// Allocate arg vector (1 more for final 0)
typedef const char *Ccharp;
Ccharp *argv;
argv = (Ccharp *)malloc((m_argv.size()+1) * sizeof(char *));
argv = (Ccharp *)malloc((m_argv.size() + 1) * sizeof(char *));
if (argv == 0) {
LOGERR(("ExecCmd::doexec: malloc() failed. errno %d\n", errno));
return;
@ -1167,7 +1192,7 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
}
// Read answer
for (int loop=0;;loop++) {
for (int loop = 0;; loop++) {
string name, data;
// Code from mh_execm.cpp: readDataElement
@ -1217,8 +1242,9 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
}
// Empty element: end of message
if (name.empty())
if (name.empty()) {
break;
}
cerr << "Got name: [" << name << "] data [" << data << "]\n";
}
}
@ -1228,19 +1254,19 @@ bool exercise_mhexecm(const string& cmdstr, const string& mimetype,
static char *thisprog;
static char usage [] =
"trexecmd [-c -r -i -o] cmd [arg1 arg2 ...]\n"
" -c : test cancellation (ie: trexecmd -c sleep 1000)\n"
" -r : run reexec. Must be separate option.\n"
" -i : command takes input\n"
" -o : command produces output\n"
" If -i is set, we send /etc/group contents to whatever command is run\n"
" If -o is set, we print whatever comes out\n"
"trexecmd -m <filter> <mimetype> <file> [file ...]: test execm:\n"
" <filter> should be the path to an execm filter\n"
" <mimetype> the type of the file parameters\n"
"trexecmd -w cmd : do the 'which' thing\n"
"trexecmd -l cmd test getline\n"
;
"trexecmd [-c -r -i -o] cmd [arg1 arg2 ...]\n"
" -c : test cancellation (ie: trexecmd -c sleep 1000)\n"
" -r : run reexec. Must be separate option.\n"
" -i : command takes input\n"
" -o : command produces output\n"
" If -i is set, we send /etc/group contents to whatever command is run\n"
" If -o is set, we print whatever comes out\n"
"trexecmd -m <filter> <mimetype> <file> [file ...]: test execm:\n"
" <filter> should be the path to an execm filter\n"
" <mimetype> the type of the file parameters\n"
"trexecmd -w cmd : do the 'which' thing\n"
"trexecmd -l cmd test getline\n"
;
static void Usage(void)
{
@ -1285,14 +1311,14 @@ public:
FILE *m_fp;
string *m_input;
MEPv(string *i)
: m_input(i)
{
: m_input(i) {
m_fp = fopen("/etc/group", "r");
}
~MEPv() {
if (m_fp)
if (m_fp) {
fclose(m_fp);
}
}
void newData() {
char line[1024];
if (m_fp && fgets(line, 1024, m_fp)) {
@ -1322,36 +1348,59 @@ int main(int argc, char *argv[])
}
thisprog = argv[0];
argc--; argv++;
argc--;
argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
{
Usage();
}
while (**argv)
switch (*(*argv)++) {
case 'c': op_flags |= OPT_c; break;
case 'r': op_flags |= OPT_r; break;
case 'w': op_flags |= OPT_w; break;
case 'c':
op_flags |= OPT_c;
break;
case 'r':
op_flags |= OPT_r;
break;
case 'w':
op_flags |= OPT_w;
break;
#ifdef BUILDING_RECOLL
case 'm': op_flags |= OPT_m; break;
case 'm':
op_flags |= OPT_m;
break;
#endif
case 'i': op_flags |= OPT_i; break;
case 'l': op_flags |= OPT_l; break;
case 'o': op_flags |= OPT_o; break;
default: Usage(); break;
}
argc--; argv++;
}
if (argc < 1)
case 'i':
op_flags |= OPT_i;
break;
case 'l':
op_flags |= OPT_l;
break;
case 'o':
op_flags |= OPT_o;
break;
default:
Usage();
break;
}
argc--;
argv++;
}
string arg1 = *argv++; argc--;
if (argc < 1) {
Usage();
}
string arg1 = *argv++;
argc--;
vector<string> l;
while (argc > 0) {
l.push_back(*argv++); argc--;
l.push_back(*argv++);
argc--;
}
#ifdef BUILDING_RECOLL
@ -1384,8 +1433,9 @@ int main(int argc, char *argv[])
return 1;
#ifdef BUILDING_RECOLL
} else if (op_flags & OPT_m) {
if (l.size() < 2)
if (l.size() < 2) {
Usage();
}
string mimetype = l[0];
l.erase(l.begin());
return exercise_mhexecm(arg1, mimetype, l) ? 0 : 1;
@ -1403,7 +1453,7 @@ int main(int argc, char *argv[])
cerr << "Waiting\n";
int status = mexec.wait();
cerr << "Got status " << status << endl;
exit (status);
exit(status);
} else {
// Default: execute command line arguments
ExecCmd mexec;
@ -1447,7 +1497,7 @@ int main(int argc, char *argv[])
if (op_flags & OPT_o) {
cout << output;
}
exit (status >> 8);
exit(status >> 8);
}
}
#endif // TEST

View file

@ -31,7 +31,7 @@
*
*/
class ExecCmdAdvise {
public:
public:
virtual ~ExecCmdAdvise() {}
virtual void newData(int cnt) = 0;
};
@ -41,7 +41,7 @@ class ExecCmdAdvise {
* into the initial input string, set it to empty to signify eof.
*/
class ExecCmdProvide {
public:
public:
virtual ~ExecCmdProvide() {}
virtual void newData() = 0;
};
@ -65,7 +65,7 @@ class ExecCmdProvide {
*
*/
class ExecCmd {
public:
public:
// Use vfork instead of fork. Our vfork usage is multithread-compatible as
// far as I can see, but just in case...
static void useVfork(bool on);
@ -76,8 +76,8 @@ class ExecCmd {
* times for several variables).
* @param envassign an environment assignment string ("name=value")
*/
void putenv(const std::string &envassign);
void putenv(const std::string &name, const std::string& value);
void putenv(const std::string& envassign);
void putenv(const std::string& name, const std::string& value);
/**
* Try to set a limit on child process vm size. This will use
@ -114,7 +114,7 @@ class ExecCmd {
* If the parameter can't be opened for writing, the command's
* stderr will be closed.
*/
void setStderr(const std::string &stderrFile);
void setStderr(const std::string& stderrFile);
/**
* Execute command.
@ -133,7 +133,7 @@ class ExecCmd {
* @param output Output FROM the command.
* @return the exec output status (0 if ok), or -1
*/
int doexec(const std::string &cmd, const std::vector<std::string>& args,
int doexec(const std::string& cmd, const std::vector<std::string>& args,
const std::string *input = 0,
std::string *output = 0);
@ -141,8 +141,9 @@ class ExecCmd {
int doexec1(const std::vector<std::string>& args,
const std::string *input = 0,
std::string *output = 0) {
if (args.empty())
if (args.empty()) {
return -1;
}
return doexec(args[0],
std::vector<std::string>(args.begin() + 1, args.end()),
input, output);
@ -152,7 +153,7 @@ class ExecCmd {
* The next four methods can be used when a Q/A dialog needs to be
* performed with the command
*/
int startExec(const std::string &cmd, const std::vector<std::string>& args,
int startExec(const std::string& cmd, const std::vector<std::string>& args,
bool has_input, bool has_output);
int send(const std::string& data);
int receive(std::string& data, int cnt = -1);
@ -221,11 +222,13 @@ class ExecCmd {
static bool backtick(const std::vector<std::string> cmd, std::string& out);
class Internal;
private:
private:
Internal *m;
/* Copyconst and assignment are private and forbidden */
ExecCmd(const ExecCmd &) {}
ExecCmd& operator=(const ExecCmd &) {return *this;};
ExecCmd(const ExecCmd&) {}
ExecCmd& operator=(const ExecCmd&) {
return *this;
};
};
@ -259,13 +262,14 @@ public:
ReExec() {}
ReExec(int argc, char *argv[]);
void init(int argc, char *argv[]);
int atexit(void (*function)(void))
{
int atexit(void (*function)(void)) {
m_atexitfuncs.push(function);
return 0;
}
void reexec();
const std::string& getreason() {return m_reason;}
const std::string& getreason() {
return m_reason;
}
// Insert new args into the initial argv. idx designates the place
// before which the new args are inserted (the default of 1
// inserts after argv[0] which would probably be an appropriate

View file

@ -116,12 +116,12 @@ int Netcon::select1(int fd, int timeo, int write)
FD_ZERO(&rd);
FD_SET(fd, &rd);
if (write) {
ret = select(fd+1, 0, &rd, 0, &tv);
ret = select(fd + 1, 0, &rd, 0, &tv);
} else {
ret = select(fd+1, &rd, 0, 0, &tv);
ret = select(fd + 1, &rd, 0, 0, &tv);
}
if (!FD_ISSET(fd, &rd)) {
LOGDEB2(("Netcon::select1: fd %d timeout\n",fd));
LOGDEB2(("Netcon::select1: fd %d timeout\n", fd));
}
return ret;
}
@ -199,11 +199,11 @@ int SelectLoop::doLoop()
// Walk the netcon map and set up the read and write fd_sets
// for select()
nfds = 0;
for (map<int,NetconP>::iterator it = m_polldata.begin();
for (map<int, NetconP>::iterator it = m_polldata.begin();
it != m_polldata.end(); it++) {
NetconP &pll = it->second;
NetconP& pll = it->second;
int fd = it->first;
LOGDEB2(("Selectloop: fd %d flags 0x%x\n",fd, pll->m_wantedEvents));
LOGDEB2(("Selectloop: fd %d flags 0x%x\n", fd, pll->m_wantedEvents));
if (pll->m_wantedEvents & Netcon::NETCONPOLL_READ) {
FD_SET(fd, &rd);
nfds = MAX(nfds, fd + 1);
@ -275,7 +275,7 @@ int SelectLoop::doLoop()
continue;
}
map<int,NetconP>::iterator it = m_polldata.find(fd);
map<int, NetconP>::iterator it = m_polldata.find(fd);
if (it == m_polldata.end()) {
/// This should not happen actually
LOGDEB2(("Netcon::selectloop: fd %d not found\n", fd));
@ -284,14 +284,14 @@ int SelectLoop::doLoop()
// Next start will be one beyond last serviced (modulo nfds)
m_placetostart = fd + 1;
NetconP &pll = it->second;
NetconP& pll = it->second;
if (canread && pll->cando(Netcon::NETCONPOLL_READ) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_READ;
}
if (canwrite && pll->cando(Netcon::NETCONPOLL_WRITE) <= 0) {
pll->m_wantedEvents &= ~Netcon::NETCONPOLL_WRITE;
}
if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE|Netcon::NETCONPOLL_READ))) {
if (!(pll->m_wantedEvents & (Netcon::NETCONPOLL_WRITE | Netcon::NETCONPOLL_READ))) {
LOGDEB0(("Netcon::selectloop: fd %d has 0x%x mask, erasing\n",
it->first, it->second->m_wantedEvents));
m_polldata.erase(it);
@ -324,7 +324,7 @@ int SelectLoop::remselcon(NetconP con)
return -1;
}
LOGDEB1(("Netcon::remselcon: fd %d\n", con->m_fd));
map<int,NetconP>::iterator it = m_polldata.find(con->m_fd);
map<int, NetconP>::iterator it = m_polldata.find(con->m_fd);
if (it == m_polldata.end()) {
LOGDEB1(("Netcon::remselcon: con not found for fd %d\n", con->m_fd));
return -1;
@ -369,7 +369,7 @@ void Netcon::setpeer(const char *hostname)
int Netcon::settcpnodelay(int on)
{
LOGDEB2(( "Netcon::settcpnodelay\n" ));
LOGDEB2(("Netcon::settcpnodelay\n"));
if (m_fd < 0) {
LOGERR(("Netcon::settcpnodelay: connection not opened\n"));
return -1;
@ -386,7 +386,7 @@ int Netcon::settcpnodelay(int on)
int Netcon::set_nonblock(int onoff)
{
int flags = fcntl(m_fd, F_GETFL, 0);
if (flags != -1 ) {
if (flags != -1) {
int newflags = onoff ? flags | O_NONBLOCK : flags & ~O_NONBLOCK;
if (newflags != flags)
if (fcntl(m_fd, F_SETFL, newflags) < 0) {
@ -511,7 +511,7 @@ int NetconData::doreceive(char *buf, int cnt, int timeo)
LOGDEB2(("Netcon::doreceive: cnt %d, timeo %d\n", cnt, timeo));
cur = 0;
while (cnt > cur) {
got = receive(buf, cnt-cur, timeo);
got = receive(buf, cnt - cur, timeo);
LOGDEB2(("Netcon::doreceive: got %d\n", got));
if (got < 0) {
return -1;
@ -551,7 +551,7 @@ int NetconData::getline(char *buf, int cnt, int timeo)
for (;;) {
// Transfer from buffer. Have to take a lot of care to keep counts and
// pointers consistant in all end cases
int maxtransf = MIN(m_bufbytes, cnt-1);
int maxtransf = MIN(m_bufbytes, cnt - 1);
int nn = maxtransf;
LOGDEB2(("Before loop, bufbytes %d, maxtransf %d, nn: %d\n",
m_bufbytes, maxtransf, nn));
@ -723,7 +723,7 @@ int NetconCli::openconn(const char *host, const char *serv, int timeo)
if (host[0] != '/') {
struct servent *sp;
if ((sp = getservbyname(serv, "tcp")) == 0) {
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n",serv));
LOGERR(("NetconCli::openconn: getservbyname failed for %s\n", serv));
return -1;
}
// Callee expects the port number in host byte order
@ -822,7 +822,7 @@ int NetconServLis::openservice(const char *serv, int backlog)
LOGDEB1(("NetconServLis::openservice: service opened ok\n"));
ret = 0;
out:
out:
if (ret < 0 && m_fd >= 0) {
close(m_fd);
m_fd = -1;
@ -846,9 +846,9 @@ int NetconServLis::openservice(int port, int backlog)
LOGSYSERR("NetconServLis", "socket", "");
return -1;
}
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR,(char *)&one, sizeof(one));
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one));
#ifdef SO_REUSEPORT
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT,(char *)&one, sizeof(one));
(void) setsockopt(m_fd, SOL_SOCKET, SO_REUSEPORT, (char *)&one, sizeof(one));
#endif /*SO_REUSEPORT*/
memset(&ipaddr, 0, sizeof(ipaddr));
ipaddr.sin_family = AF_INET;
@ -1033,7 +1033,7 @@ NetconServLis::checkperms(void *cl, int)
if (i < okmasks.len) {
mask = okmasks.intarray[i];
} else {
mask = okmasks.intarray[okmasks.len-1];
mask = okmasks.intarray[okmasks.len - 1];
}
LOGDEB2(("checkperms: trying okaddr 0x%x, mask 0x%x\n",
okaddrs.intarray[i], mask));
@ -1271,7 +1271,7 @@ public:
}
if (reason & Netcon::NETCONPOLL_READ) {
#define LL 200
char buf[LL+1];
char buf[LL + 1];
int n;
if ((n = con->receive(buf, LL)) < 0) {
fprintf(stderr, "receive failed\n");
@ -1282,7 +1282,7 @@ public:
}
buf[n] = 0;
fprintf(stderr, "%d received \"%s\"\n", getpid(), buf);
con->setselevents(Netcon::NETCONPOLL_READ|Netcon::NETCONPOLL_WRITE);
con->setselevents(Netcon::NETCONPOLL_READ | Netcon::NETCONPOLL_WRITE);
}
return 0;
}
@ -1292,7 +1292,7 @@ private:
class MyNetconServLis : public NetconServLis {
public:
MyNetconServLis(SelectLoop &loop)
MyNetconServLis(SelectLoop& loop)
: NetconServLis(), m_loop(loop) {
}
protected:

View file

@ -48,7 +48,7 @@ class SelectLoop;
class Netcon {
public:
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE=0x2};
enum Event {NETCONPOLL_READ = 0x1, NETCONPOLL_WRITE = 0x2};
Netcon()
: m_peer(0), m_fd(-1), m_ownfd(true), m_didtimo(0), m_wantedEvents(0),
m_loop(0) {

View file

@ -22,12 +22,16 @@
#endif
#include <errno.h>
#include "safefcntl.h"
#include <sys/types.h>
#ifdef _WIN32
#include "safefcntl.h"
#include "safesysstat.h"
#include "safeunistd.h"
#ifndef _WIN32
#else
#define O_BINARY 0
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <string>
@ -41,8 +45,9 @@ public:
FileToString(string& data) : m_data(data) {}
string& m_data;
bool init(size_t size, string *reason) {
if (size > 0)
if (size > 0) {
m_data.reserve(size);
}
return true;
}
bool data(const char *buf, int cnt, string *reason) {
@ -56,18 +61,18 @@ public:
}
};
bool file_to_string(const string &fn, string &data, string *reason)
bool file_to_string(const string& fn, string& data, string *reason)
{
return file_to_string(fn, data, 0, size_t(-1), reason);
}
bool file_to_string(const string &fn, string &data, off_t offs, size_t cnt,
bool file_to_string(const string& fn, string& data, off_t offs, size_t cnt,
string *reason)
{
FileToString accum(data);
return file_scan(fn, &accum, offs, cnt, reason);
}
bool file_scan(const string &fn, FileScanDo* doer, string *reason)
bool file_scan(const string& fn, FileScanDo* doer, string *reason)
{
return file_scan(fn, doer, 0, size_t(-1), reason);
}
@ -77,7 +82,7 @@ const int RDBUFSZ = 8192;
// on both linux i586 and macosx (compared to just append())
// Also tried a version with mmap, but it's actually slower on the mac and not
// faster on linux.
bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
bool file_scan(const string& fn, FileScanDo* doer, off_t startoffs,
size_t cnttoread, string *reason)
{
if (startoffs < 0) {
@ -94,7 +99,7 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
// If we have a file name, open it, else use stdin.
if (!fn.empty()) {
fd = open(fn.c_str(), O_RDONLY|O_BINARY);
fd = open(fn.c_str(), O_RDONLY | O_BINARY);
if (fd < 0 || fstat(fd, &st) < 0) {
catstrerror(reason, "open/stat", errno);
return false;
@ -108,10 +113,10 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
}
#endif
if (cnttoread != (size_t)-1 && cnttoread) {
doer->init(cnttoread+1, reason);
if (cnttoread != (size_t) - 1 && cnttoread) {
doer->init(cnttoread + 1, reason);
} else if (st.st_size > 0) {
doer->init(size_t(st.st_size+1), reason);
doer->init(size_t(st.st_size + 1), reason);
} else {
doer->init(0, reason);
}
@ -141,25 +146,29 @@ bool file_scan(const string &fn, FileScanDo* doer, off_t startoffs,
catstrerror(reason, "read", errno);
goto out;
}
if (n == 0)
if (n == 0) {
break;
}
curoffs += n;
if (curoffs - n < startoffs)
if (curoffs - n < startoffs) {
continue;
}
if (!doer->data(buf, n, reason)) {
goto out;
}
totread += n;
if (cnttoread > 0 && totread >= cnttoread)
if (cnttoread > 0 && totread >= cnttoread) {
break;
}
}
ret = true;
out:
if (fd >= 0 && !noclosing)
out:
if (fd >= 0 && !noclosing) {
close(fd);
}
return ret;
}
@ -181,11 +190,10 @@ using namespace std;
using namespace std;
class myCB : public FsTreeWalkerCB {
public:
FsTreeWalker::Status processone(const string &path,
public:
FsTreeWalker::Status processone(const string& path,
const struct stat *st,
FsTreeWalker::CbFlag flg)
{
FsTreeWalker::CbFlag flg) {
if (flg == FsTreeWalker::FtwDirEnter) {
//cout << "[Entering " << path << "]" << endl;
} else if (flg == FsTreeWalker::FtwDirReturn) {
@ -214,8 +222,8 @@ static int op_flags;
static const char *thisprog;
static char usage [] =
"trreadfile [-o offs] [-c cnt] topdirorfile\n\n"
;
"trreadfile [-o offs] [-c cnt] topdirorfile\n\n"
;
static void
Usage(void)
{
@ -228,29 +236,48 @@ int main(int argc, const char **argv)
off_t offs = 0;
size_t cnt = size_t(-1);
thisprog = argv[0];
argc--; argv++;
argc--;
argv++;
while (argc > 0 && **argv == '-') {
(*argv)++;
if (!(**argv))
/* Cas du "adb - core" */
{
Usage();
}
while (**argv)
switch (*(*argv)++) {
case 'c': op_flags |= OPT_c; if (argc < 2) Usage();
cnt = atoll(*(++argv)); argc--;
goto b1;
case 'o': op_flags |= OPT_o; if (argc < 2) Usage();
offs = strtoull(*(++argv), 0, 0); argc--;
goto b1;
default: Usage(); break;
case 'c':
op_flags |= OPT_c;
if (argc < 2) {
Usage();
}
b1: argc--; argv++;
cnt = atoll(*(++argv));
argc--;
goto b1;
case 'o':
op_flags |= OPT_o;
if (argc < 2) {
Usage();
}
offs = strtoull(*(++argv), 0, 0);
argc--;
goto b1;
default:
Usage();
break;
}
b1:
argc--;
argv++;
}
if (argc != 1)
if (argc != 1) {
Usage();
string top = *argv++;argc--;
}
string top = *argv++;
argc--;
cerr << "filename " << top << " offs " << offs << " cnt " << cnt << endl;
struct stat st;
@ -262,8 +289,9 @@ int main(int argc, const char **argv)
FsTreeWalker walker;
myCB cb;
walker.walk(top, cb);
if (walker.getErrCnt() > 0)
if (walker.getErrCnt() > 0) {
cout << walker.getReason();
}
} else {
string s, reason;
if (!file_to_string(top, s, offs, cnt, &reason)) {

View file

@ -31,20 +31,20 @@ public:
virtual bool init(size_t size, std::string *reason) = 0;
virtual bool data(const char *buf, int cnt, std::string* reason) = 0;
};
bool file_scan(const std::string &filename, FileScanDo* doer, std::string *reason = 0);
bool file_scan(const std::string& filename, FileScanDo* doer, std::string *reason = 0);
/* Same but only process count cnt from offset offs. Set cnt to size_t(-1)
* for no limit */
bool file_scan(const std::string &fn, FileScanDo* doer, off_t offs, size_t cnt,
bool file_scan(const std::string& fn, FileScanDo* doer, off_t offs, size_t cnt,
std::string *reason = 0);
/**
* Read file into string.
* @return true for ok, false else
*/
bool file_to_string(const std::string &filename, std::string &data, std::string *reason = 0);
bool file_to_string(const std::string& filename, std::string& data, std::string *reason = 0);
/** Read file chunk into string. Set cnt to size_t(-1) for whole file */
bool file_to_string(const std::string &filename, std::string &data,
bool file_to_string(const std::string& filename, std::string& data,
off_t offs, size_t cnt, std::string *reason = 0);
#endif /* _READFILE_H_INCLUDED_ */