execve_hook/tests/socket-client/client.c

182 lines
4.8 KiB
C

#include "client.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <netinet/tcp.h>
#define BUFFER_SIZE 4096
// 读取完整消息
ssize_t readMessage(int sock, char *buffer, size_t maxSize) {
uint32_t messageLen;
// 先读取消息长度
if (read(sock, &messageLen, sizeof(messageLen)) != sizeof(messageLen)) {
return -1;
}
// 检查buffer大小是否足够
if (messageLen >= maxSize) {
return -1;
}
// 读取完整消息
size_t totalRead = 0;
while (totalRead < messageLen) {
ssize_t n = read(sock, buffer + totalRead, messageLen - totalRead);
if (n <= 0) return -1;
totalRead += n;
}
buffer[messageLen] = '\0';
return messageLen;
}
int send_exec_params(const char *filename, char *const argv[],
char *const envp[], const char *logPath) {
char abs_path[PATH_MAX];
char pwd[PATH_MAX];
// 获取当前工作目录
if (getcwd(pwd, sizeof(pwd)) == NULL) {
perror("getcwd");
return -1;
}
if (logPath[0] != '/') { // 相对路径
size_t pwd_len = strlen(pwd);
size_t log_len = strlen(logPath);
if (pwd_len + log_len + 2 > PATH_MAX) {
errno = ENAMETOOLONG;
perror("path too long");
return -1;
}
strncpy(abs_path, pwd, PATH_MAX - 1);
abs_path[PATH_MAX - 1] = '\0';
strncat(abs_path, "/", PATH_MAX - strlen(abs_path) - 1);
strncat(abs_path, logPath, PATH_MAX - strlen(abs_path) - 1);
char real_path[PATH_MAX];
if (realpath(abs_path, real_path) == NULL) {
perror("realpath");
return -1;
}
strncpy(abs_path, real_path, PATH_MAX - 1);
abs_path[PATH_MAX - 1] = '\0';
} else {
strncpy(abs_path, logPath, PATH_MAX - 1);
abs_path[PATH_MAX - 1] = '\0';
}
size_t path_len = strlen(abs_path);
int sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (sock == -1) {
perror("socket");
return -1;
}
// 设置TCP_NODELAY
// int flag = 1;
// setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(int));
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1);
addr.sun_path[sizeof(addr.sun_path) - 1] = '\0';
if (connect(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("connect");
close(sock);
return -1;
}
// 发送文件名
size_t filename_len = strlen(filename);
write(sock, &filename_len, sizeof(size_t));
write(sock, filename, filename_len);
// 发送当前工作目录
size_t pwd_len = strlen(pwd);
write(sock, &pwd_len, sizeof(size_t));
write(sock, pwd, pwd_len);
// 发送argv
int argc = 0;
while (argv[argc] != NULL) argc++;
write(sock, &argc, sizeof(int));
for (int i = 0; i < argc; i++) {
size_t arg_len = strlen(argv[i]);
write(sock, &arg_len, sizeof(size_t));
write(sock, argv[i], arg_len);
}
// 发送envp
int envc = 0;
while (envp[envc] != NULL) envc++;
write(sock, &envc, sizeof(int));
for (int i = 0; i < envc; i++) {
size_t env_len = strlen(envp[i]);
write(sock, &env_len, sizeof(size_t));
write(sock, envp[i], env_len);
}
// 发送logPath
write(sock, &path_len, sizeof(size_t));
write(sock, abs_path, path_len);
// 接收服务器响应
char buffer[BUFFER_SIZE];
char display_buffer[BUFFER_SIZE];
ssize_t bytes_read;
int started = 0;
// 等待接收[sthttp]标记
while (!started) {
bytes_read = readMessage(sock, buffer, BUFFER_SIZE);
if (bytes_read <= 0) {
perror("Failed to read start marker");
close(sock);
return -1;
}
if (strstr(buffer, "[sthttp]")) {
started = 1;
}
}
// 持续读取消息直到收到[end]
while (1) {
bytes_read = readMessage(sock, buffer, BUFFER_SIZE);
if (bytes_read <= 0) {
break;
}
if (strstr(buffer, "[end]")) {
break;
}
// 处理[res]...[wait]消息
char *res_start = strstr(buffer, "[res]");
char *wait_end = strstr(buffer, "[wait]");
if (res_start && wait_end) {
size_t content_len = wait_end - (res_start + strlen("[res]"));
if (content_len < BUFFER_SIZE) {
strncpy(display_buffer, res_start + strlen("[res]"), content_len);
display_buffer[content_len] = '\0';
printf("%s\n", display_buffer);
fflush(stdout);
}
}
}
close(sock);
return 0;
}