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