#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; }