273 lines
7.2 KiB
C
273 lines
7.2 KiB
C
#include "common.h"
|
||
|
||
// 计算字符串长度
|
||
int _strlen(const char *str) {
|
||
if (str == NULL)
|
||
return 0;
|
||
|
||
const char *_p = strchr(str, '\0');
|
||
return _p - str;
|
||
}
|
||
|
||
|
||
// 自定义 printf 函数
|
||
void _printf(const char *format, ...)
|
||
{
|
||
va_list args;
|
||
va_start(args, format);
|
||
|
||
// 获取当前时间
|
||
time_t now = time(NULL);
|
||
struct tm local_time;
|
||
localtime_r(&now, &local_time);
|
||
char time_str[20]; // YYYY-MM-DD HH:MM:SS 格式
|
||
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", &local_time);
|
||
|
||
// 打印时间戳到控制台
|
||
printf("[%s] ", time_str);
|
||
vprintf(format, args); // 打印内容到控制台
|
||
va_end(args); // 结束对变参列表的处理
|
||
|
||
// 重新启动变参列表
|
||
va_start(args, format);
|
||
|
||
// 打开日志文件(追加模式)
|
||
FILE *log_file = fopen(PRINT_LOG_FILE, "a");
|
||
if (log_file != NULL) {
|
||
// 打印时间戳到日志文件
|
||
fprintf(log_file, "[%s] ", time_str);
|
||
|
||
// 打印内容到日志文件
|
||
vfprintf(log_file, format, args);
|
||
|
||
// 关闭日志文件
|
||
fclose(log_file);
|
||
} else {
|
||
perror("Unable to open log file");
|
||
}
|
||
|
||
va_end(args); // 结束对变参列表的处理
|
||
}
|
||
|
||
void split_string(char string[], char delims[], char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||
{
|
||
int i = 0;
|
||
char *result = NULL;
|
||
char temp[WHITELIST_IP_NUM]; // 创建一个足够大的副本缓冲区
|
||
|
||
// 复制原始字符串到副本
|
||
strncpy(temp, string, sizeof(temp) - 1);
|
||
temp[sizeof(temp) - 1] = '\0'; // 确保字符串以 '\0' 结尾
|
||
|
||
result = strtok(temp, delims); // 使用副本进行拆分
|
||
while (result != NULL && i < WHITELIST_IP_NUM)
|
||
{
|
||
strncpy(whitelist_ip[i], result, WHITELIST_IP_NUM - 1);
|
||
whitelist_ip[i][WHITELIST_IP_NUM - 1] = '\0'; // 确保每个元素以 '\0' 结尾
|
||
i++;
|
||
result = strtok(NULL, delims);
|
||
}
|
||
}
|
||
|
||
// IP段白名单对比
|
||
int whitelist(char *client_ip, char (*whitelist_ip)[WHITELIST_IP_NUM])
|
||
{
|
||
int i;
|
||
|
||
for (i = 0; i < WHITELIST_IP_NUM; i++) { // 从 i = 0 开始
|
||
// 如果白名单 IP 是空字符串,跳出循环
|
||
if (whitelist_ip[i][0] == '\0') {
|
||
break;
|
||
}
|
||
|
||
// 对比 client_ip 的前缀是否与白名单中的IP段匹配
|
||
if (strncmp(client_ip, whitelist_ip[i], strlen(whitelist_ip[i])) == 0) {
|
||
return 1; // 匹配成功
|
||
}
|
||
}
|
||
|
||
return 0; // 未找到匹配
|
||
}
|
||
|
||
// 地域段白名单对比
|
||
int isregion(char *str, char (*region_list)[WHITELIST_IP_NUM])
|
||
{
|
||
int i;
|
||
char *p;
|
||
|
||
for (i = 0; i < WHITELIST_IP_NUM; i++) {
|
||
// 如果 region_list[i] 为空字符串,跳出循环
|
||
if (region_list[i][0] == '\0') {
|
||
break;
|
||
}
|
||
|
||
// 在str中查找 region_list[i]
|
||
p = strstr(str, region_list[i]);
|
||
if (p != NULL) {
|
||
return 1; // 匹配成功,返回1
|
||
}
|
||
}
|
||
|
||
return 0; // 没有匹配,返回0
|
||
}
|
||
|
||
int8_t _copy_new_mem(char *src, int src_len, char **dest)
|
||
{
|
||
*dest = (char *)malloc(src_len + 1);
|
||
if (*dest == NULL)
|
||
return 1;
|
||
memcpy(*dest, src, src_len);
|
||
*((*dest) + src_len) = '\0';
|
||
|
||
return 0;
|
||
}
|
||
|
||
// 返回的时间字符串存储在静态缓冲区中
|
||
char *_time() {
|
||
static char temp[BUFFER];
|
||
const char *wday[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||
time_t t = time(NULL);
|
||
struct tm *p = localtime(&t);
|
||
|
||
if (!p) {
|
||
perror("localtime failed");
|
||
return NULL;
|
||
}
|
||
|
||
snprintf(temp, sizeof(temp), "[%d/%02d/%02d %s %02d:%02d:%02d]",
|
||
1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday,
|
||
wday[p->tm_wday], p->tm_hour, p->tm_min, p->tm_sec);
|
||
|
||
return temp; // 返回静态缓冲区地址
|
||
}
|
||
|
||
// 将字符串转换为IPv4地址
|
||
int is_valid_ip(const char *ip)
|
||
{
|
||
struct sockaddr_in sa;
|
||
// 将字符串转换为IPv4地址
|
||
int result = inet_pton(AF_INET, ip, &(sa.sin_addr));
|
||
|
||
return result != 0;
|
||
}
|
||
|
||
// 修改进程优先级
|
||
int _nice(int increment) {
|
||
// 获取当前优先级
|
||
int oldprio = getpriority(PRIO_PROCESS, getpid());
|
||
if (oldprio == -1 && errno != 0) {
|
||
perror("getpriority failed");
|
||
return -1;
|
||
}
|
||
|
||
printf("Current priority: %d\n", oldprio);
|
||
|
||
// 检查是否溢出
|
||
if ((increment > 0 && oldprio > INT_MAX - increment) ||
|
||
(increment < 0 && oldprio < INT_MIN - increment)) {
|
||
fprintf(stderr, "Priority overflow error\n");
|
||
return -1;
|
||
}
|
||
|
||
// 计算新的优先级
|
||
int newprio = oldprio + increment;
|
||
|
||
// 检查新的优先级是否在有效范围内
|
||
if (newprio < PRIO_MIN || newprio > PRIO_MAX) {
|
||
fprintf(stderr, "New priority out of range: %d (valid range is %d to %d)\n", newprio, PRIO_MIN, PRIO_MAX);
|
||
return -1;
|
||
}
|
||
|
||
// 设置新的优先级
|
||
if (setpriority(PRIO_PROCESS, getpid(), newprio) == -1) {
|
||
perror("setpriority failed");
|
||
return -1;
|
||
}
|
||
|
||
printf("New priority: %d\n", newprio);
|
||
return 0;
|
||
}
|
||
|
||
// 判断命令是否存在
|
||
int command_exists(const char *command) {
|
||
const char *path_env = getenv("PATH");
|
||
if (!path_env) {
|
||
return 0; // 如果 PATH 不存在,返回不存在
|
||
}
|
||
|
||
char filepath[1024]; // 缓冲区大小
|
||
const char *dir = path_env;
|
||
|
||
while (dir && *dir) {
|
||
// 查找 PATH 中的下一个目录
|
||
const char *end = strchr(dir, ':');
|
||
size_t len = end ? (size_t)(end - dir) : strlen(dir);
|
||
|
||
// 构建路径并检查长度
|
||
if (snprintf(filepath, sizeof(filepath), "%.*s/%s", (int)len, dir, command) >= (int)sizeof(filepath)) {
|
||
return 0; // 缓冲区溢出,返回不存在
|
||
}
|
||
|
||
// 检查文件是否存在且可执行
|
||
if (access(filepath, X_OK) == 0) {
|
||
puts(filepath);
|
||
return 1; // 命令存在
|
||
}
|
||
|
||
// 更新 dir 指针
|
||
dir = end ? end + 1 : NULL;
|
||
}
|
||
|
||
return 0; // 命令不存在
|
||
}
|
||
|
||
// 定义一个函数,执行命令并返回输出
|
||
char *_execute_command(const char *command) {
|
||
FILE *fp;
|
||
char buffer[1024];
|
||
char *output = NULL;
|
||
size_t output_size = 0;
|
||
size_t total_read = 0;
|
||
|
||
// 打开管道,执行命令
|
||
fp = popen(command, "r");
|
||
if (fp == NULL) {
|
||
perror("popen");
|
||
return NULL;
|
||
}
|
||
|
||
// 读取命令的输出
|
||
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
|
||
size_t len = strlen(buffer);
|
||
if (total_read + len + 1 > output_size) {
|
||
output_size = output_size == 0 ? 128 : output_size * 2;
|
||
char *new_output = realloc(output, output_size);
|
||
if (new_output == NULL) {
|
||
perror("realloc");
|
||
free(output); // 释放已分配的内存
|
||
pclose(fp); // 关闭管道
|
||
return NULL;
|
||
}
|
||
output = new_output;
|
||
}
|
||
// 复制内容并增加总计读取的长度
|
||
strcpy(output + total_read, buffer);
|
||
total_read += len;
|
||
}
|
||
|
||
// 确保输出以 null 结尾
|
||
if (output_size > 0) {
|
||
output[total_read] = '\0';
|
||
}
|
||
|
||
// 关闭管道
|
||
if (pclose(fp) == -1) {
|
||
perror("pclose");
|
||
free(output); // pclose 失败时释放内存
|
||
return NULL;
|
||
}
|
||
|
||
return output;
|
||
}
|
||
|