common.c (2665B)
1 #include "common.h" 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <string.h> 6 #include <sys/ioctl.h> 7 #include <unistd.h> 8 9 #ifndef NULL 10 #define NULL (void *)0 11 #endif 12 13 struct cli_command *cli_commands = NULL; 14 15 const char *cli_find_arg(int argc, const char **argv, const char *name) { 16 for (int i = 0; i < argc - 1; i++) 17 if (strcmp(argv[i], name) == 0) return argv[i + 1]; 18 return NULL; 19 } 20 21 size_t cli_collect_positional(int argc, const char **argv, int start, const char **out, size_t max_out) { 22 size_t n = 0; 23 for (int i = start; i < argc && n < max_out; i++) { 24 if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] != '\0') { 25 i++; 26 continue; 27 } 28 out[n++] = argv[i]; 29 } 30 return n; 31 } 32 33 const char *cli_resolve_default_config(void) { 34 static char buf[1024]; 35 const char *home = getenv("HOME"); 36 if (home) { 37 snprintf(buf, sizeof(buf), "%s/.config/udphole.conf", home); 38 if (access(buf, R_OK) == 0) return buf; 39 snprintf(buf, sizeof(buf), "%s/.udphole.conf", home); 40 if (access(buf, R_OK) == 0) return buf; 41 } 42 if (access("/etc/udphole/udphole.conf", R_OK) == 0) return "/etc/udphole/udphole.conf"; 43 if (access("/etc/udphole.conf", R_OK) == 0) return "/etc/udphole.conf"; 44 return NULL; 45 } 46 47 int cli_get_output_width(int default_width) { 48 if (!isatty(STDOUT_FILENO)) return default_width; 49 struct winsize w; 50 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) < 0 || w.ws_col <= 0) return default_width; 51 return (int)w.ws_col; 52 } 53 54 void cli_print_wrapped(FILE *out, const char *text, int width, int left_col_width) { 55 if (!text || width <= left_col_width) return; 56 char *copy = strdup(text); 57 if (!copy) return; 58 int len = left_col_width; 59 char *tok = strtok(copy, " "); 60 while (tok) { 61 int toklen = (int)strlen(tok); 62 if (len + 1 + toklen > width) { 63 fprintf(out, "\n%*s", left_col_width, ""); 64 len = left_col_width; 65 } 66 if (len > left_col_width) fputc(' ', out); 67 fputs(tok, out); 68 len += (len > left_col_width ? 1 : 0) + toklen; 69 tok = strtok(NULL, " "); 70 } 71 free(copy); 72 } 73 74 void cli_register_command(const char *name, const char *description, int (*fn)(int, const char **)) { 75 struct cli_command *cmd = malloc(sizeof(*cmd)); 76 cmd->cmd = name; 77 cmd->desc = description; 78 cmd->fn = fn; 79 cmd->next = cli_commands; 80 cli_commands = cmd; 81 } 82 83 int cli_execute_command(int argc, const char **argv) { 84 struct cli_command *cmd = cli_commands; 85 86 while (cmd) { 87 if (!strcmp(cmd->cmd, argv[0])) return cmd->fn(argc, argv); 88 cmd = cmd->next; 89 } 90 91 fprintf(stderr, "Unknown command: %s\n", argv[0]); 92 return 1; 93 }