Skip to content

Commit

Permalink
Abstract execv().
Browse files Browse the repository at this point in the history
  • Loading branch information
jrfonseca committed Nov 11, 2011
1 parent 3984ad2 commit 03c5d3d
Show file tree
Hide file tree
Showing 6 changed files with 195 additions and 23 deletions.
8 changes: 3 additions & 5 deletions cli/cli_diff.cpp
Expand Up @@ -30,6 +30,7 @@

#include "cli.hpp"
#include "os_path.hpp"
#include "os_process.hpp"
#include "trace_tools.hpp"

static const char *synopsis = "Identify differences between two traces.";
Expand Down Expand Up @@ -95,16 +96,13 @@ command(int argc, char *argv[])

#ifdef _WIN32
std::cerr << "The 'apitrace diff' command is not yet supported on this O/S.\n";
return 1;
#else
os::Path apitrace = os::getProcessName();
setenv("APITRACE", apitrace.str(), 1);

execv(command.str(), args);
return os::execute(args);
#endif

std::cerr << "Error: Failed to execute " << argv[0] << "\n";

return 1;
}

const Command diff_command = {
Expand Down
22 changes: 8 additions & 14 deletions cli/cli_diff_state.cpp
Expand Up @@ -30,6 +30,7 @@

#include "cli.hpp"
#include "os_path.hpp"
#include "os_process.hpp"
#include "trace_tools.hpp"

static const char *synopsis = "Identify differences between two state dumps.";
Expand Down Expand Up @@ -86,22 +87,15 @@ command(int argc, char *argv[])
APITRACE_SCRIPTS_INSTALL_DIR "/" CLI_DIFF_STATE_COMMAND,
true);

char* args[4];
char *args[5];

args[0] = (char *) command.str();
args[1] = file1;
args[2] = file2;
args[3] = NULL;
args[0] = const_cast<char *>("python");
args[1] = const_cast<char *>(command.str());
args[2] = file1;
args[3] = file2;
args[4] = NULL;

#ifdef _WIN32
std::cerr << "The 'apitrace diff-state' command is not yet supported on this O/S.\n";
#else
execv(command.str(), args);
#endif

std::cerr << "Error: Failed to execute " << argv[0] << "\n";

return 1;
return os::execute(args);
}

const Command diff_state_command = {
Expand Down
21 changes: 21 additions & 0 deletions common/os_posix.cpp
Expand Up @@ -31,6 +31,7 @@

#include <unistd.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <pthread.h>
#include <sys/stat.h>
#include <fcntl.h>
Expand Down Expand Up @@ -143,6 +144,26 @@ Path::exists(void) const
return true;
}

int execute(char * const * args)
{
pid_t pid = fork();
if (pid == 0) {
// child
execvp(args[0], args);
fprintf(stderr, "error: failed to execute %s\n", args[0]);
exit(-1);
} else {
// parent
if (pid == -1) {
fprintf(stderr, "error: failed to fork\n");
return -1;
}
int status = -1;
waitpid(pid, &status, 0);
return status;
}
}

void
log(const char *format, ...)
{
Expand Down
45 changes: 45 additions & 0 deletions common/os_process.hpp
@@ -0,0 +1,45 @@
/**************************************************************************
*
* Copyright 2011 Jose Fonseca
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
**************************************************************************/

/*
* Sub-process abstraction.
*/

#ifndef _OS_PROCESS_HPP_
#define _OS_PROCESS_HPP_


#include "os.hpp"


namespace os {


int execute(char * const * args);


} /* namespace os */

#endif /* _OS_PROCESS_HPP_ */
112 changes: 112 additions & 0 deletions common/os_win32.cpp
Expand Up @@ -29,6 +29,8 @@
#include <string.h>
#include <stdio.h>

#include <string>

#include "os.hpp"
#include "os_path.hpp"

Expand Down Expand Up @@ -97,6 +99,116 @@ Path::exists(void) const
return attrs != INVALID_FILE_ATTRIBUTES;
}

/**
* Determine whether an argument should be quoted.
*/
static bool
needsQuote(const char *arg)
{
char c;
while (true) {
c = *arg++;
if (c == '\0') {
break;
}
if (c == ' ' || c == '\t' || c == '\"') {
return true;
}
if (c == '\\') {
c = *arg++;
if (c == '\0') {
break;
}
if (c == '"') {
return true;
}
}
}
return false;
}

static void
quoteArg(std::string &s, const char *arg)
{
char c;
unsigned backslashes = 0;

s.push_back('"');
while (true) {
c = *arg++;
switch (c)
if (c == '\0') {
break;
} else if (c == '"') {
while (backslashes) {
s.push_back('\\');
--backslashes;
}
s.push_back('\\');
} else {
if (c == '\\') {
++backslashes;
} else {
backslashes = 0;
}
}
s.push_back(c);
}
s.push_back('"');
}

int execute(char * const * args)
{
std::string commandLine;

const char *arg0 = *args;
const char *arg;
char sep = 0;
while ((arg = *args++) != NULL) {
if (sep) {
commandLine.push_back(sep);
}

if (needsQuote(arg)) {
quoteArg(commandLine, arg);
} else {
commandLine.append(arg);
}

sep = ' ';
}

STARTUPINFO startupInfo;
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);

PROCESS_INFORMATION processInformation;

if (!CreateProcessA(NULL,
const_cast<char *>(commandLine.c_str()), // only modified by CreateProcessW
0, // process attributes
0, // thread attributes
FALSE, // inherit handles
0, // creation flags,
NULL, // environment
NULL, // current directory
&startupInfo,
&processInformation
)) {
log("error: failed to execute %s\n", arg0);
}

WaitForSingleObject(processInformation.hProcess, INFINITE);

DWORD exitCode = ~0;
GetExitCodeProcess(processInformation.hProcess, &exitCode);

CloseHandle(processInformation.hProcess);
CloseHandle(processInformation.hThread);

return (int)exitCode;
}

void
log(const char *format, ...)
{
Expand Down
10 changes: 6 additions & 4 deletions common/trace_tools_trace.cpp
Expand Up @@ -31,6 +31,7 @@
#include <iostream>

#include "os_path.hpp"
#include "os_process.hpp"
#include "trace_tools.hpp"


Expand Down Expand Up @@ -127,6 +128,8 @@ traceProgram(API api,
APITRACE_WRAPPER_INSTALL_DIR "\n"
"to the directory with the application to trace, then run the application.\n";

return 1;

#else

#if defined(__APPLE__)
Expand Down Expand Up @@ -155,17 +158,16 @@ traceProgram(API api,
std::cerr << "\n";
}

execvp(argv[0], argv);
int status = os::execute(argv);

unsetenv(TRACE_VARIABLE);
if (output) {
unsetenv("TRACE_FILE");
}

std::cerr << "error: Failed to execute " << argv[0] << "\n";
return status;
#endif

return 1;
}


Expand Down

0 comments on commit 03c5d3d

Please sign in to comment.