/*
- * Copyright 2016 Andrei Pangin
+ * Copyright jattach authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
strcpy(data.strJvm, "jvm");
strcpy(data.strEnqueue, "_JVM_EnqueueOperation");
strcpy(data.pipeName, pipeName);
+ data.args[0][0] = data.args[1][0] = data.args[2][0] = data.args[3][0] = 0;
+ // jcmd has 2 arguments maximum; merge excessive arguments into one
+ int cmd_args = argc >= 2 && strcmp(argv[0], "jcmd") == 0 ? 2 : argc >= 4 ? 4 : argc;
+
+ size_t n = 0;
int i;
- for (i = 0; i < 4; i++) {
- strcpy(data.args[i], i < argc ? argv[i] : "");
+ for (i = 0; i < argc; i++) {
+ if (i < cmd_args) {
+ n = snprintf(data.args[i], sizeof(data.args[i]), "%s", argv[i]);
+ } else if (n < sizeof(data.args[cmd_args - 1])) {
+ n += snprintf(data.args[cmd_args - 1] + n, sizeof(data.args[cmd_args - 1]) - n, " %s", argv[i]);
+ }
}
LPVOID remoteData = VirtualAllocEx(hProcess, NULL, sizeof(CallData), MEM_COMMIT, PAGE_READWRITE);
}
// JVM response is read from the pipe and mirrored to stdout
-static int read_response(HANDLE hPipe) {
+static int read_response(HANDLE hPipe, int print_output) {
ConnectNamedPipe(hPipe, NULL);
char buf[8192];
buf[bytesRead] = 0;
int result = atoi(buf);
- do {
- fwrite(buf, 1, bytesRead, stdout);
- } while (ReadFile(hPipe, buf, sizeof(buf), &bytesRead, NULL));
+ if (print_output) {
+ // Mirror JVM response to stdout
+ printf("JVM response code = ");
+ do {
+ fwrite(buf, 1, bytesRead, stdout);
+ } while (ReadFile(hPipe, buf, sizeof(buf), &bytesRead, NULL));
+ printf("\n");
+ }
return result;
}
-int jattach(int pid, int argc, char** argv) {
+int jattach(int pid, int argc, char** argv, int print_output) {
// When attaching as an Administrator, make sure the target process can connect to our pipe,
// i.e. allow read-write access to everyone. For the complete format description, see
// https://docs.microsoft.com/en-us/windows/win32/secauthz/security-descriptor-string-format
sprintf(pipeName, "\\\\.\\pipe\\javatool%d", GetTickCount());
HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1, 4096, 8192, NMPWAIT_USE_DEFAULT_WAIT, &sec);
- if (hPipe == NULL) {
+ if (hPipe == INVALID_HANDLE_VALUE) {
print_error("Could not create pipe", GetLastError());
LocalFree(sec.lpSecurityDescriptor);
return 1;
return 1;
}
- printf("Response code = ");
- fflush(stdout);
-
- int result = read_response(hPipe);
- printf("\n");
+ int result = read_response(hPipe, print_output);
CloseHandle(hPipe);
return result;
int main(int argc, char** argv) {
if (argc < 3) {
printf("jattach " JATTACH_VERSION " built on " __DATE__ "\n"
- "Copyright 2021 Andrei Pangin\n"
"\n"
"Usage: jattach <pid> <cmd> [args ...]\n"
"\n"
return 1;
}
- return jattach(pid, argc - 2, argv + 2);
+ return jattach(pid, argc - 2, argv + 2, 1);
}
#endif // JATTACH_VERSION