/* ************************************************************************** */ /* */ /* ::: :::::::: */ /* flags.c :+: :+: :+: */ /* +:+ +:+ +:+ */ /* By: rparodi +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2026/03/30 12:06:19 by rparodi #+# #+# */ /* Updated: 2026/03/30 12:40:57 by rparodi ### ########.fr */ /* */ /* ************************************************************************** */ #include "parsing.h" #include "macro.h" #include #include #include #include #include #include #include #include #include const t_args _flags[] = { {'?', "help", NULL, "print help and exit", true}, {'W', "linger",",", "time to wait for response", false}, {'c', "count","", "stop after replies", false}, {'f', "flood",NULL, "flood ping", false}, {'l', "preload",",", "send number of packages while waiting replies", false}, {'n', "numeric",NULL, "no reverse DNS name resolution", false}, {'p', "pattern",",", "contents of padding byte", false}, {'q', "quiet", NULL, "reply wait in seconds", false}, {'v', "verbose",NULL, "verbose output", true}, {'w', "timeout",",", "reply wait in seconds", false}, {0, "usage", NULL, "give a short usage message", false}, {0, NULL, NULL,NULL, true}, }; static struct option *_t_args_to_getopt_long(const size_t size) { struct option *long_options = (struct option *)calloc((size + 1), sizeof(struct option)); if (!long_options) { return NULL; } for (size_t i = 0; i < size; i++) { long_options[i].name = _flags[i].long_option; long_options[i].val = _flags[i].short_option; if (_flags[i].usage == NULL) { long_options[i].has_arg = no_argument; } else { long_options[i].has_arg = required_argument; } long_options[i].flag = NULL; } long_options[size] = (struct option){0}; return long_options; } void check_flags(int argc, char **argv, t_flags *flags) { const size_t size = args_size(); size_t j = 0; char args[2 * size + 1]; bzero(args, sizeof(args)); for (size_t i = 0; i < size; i++) { if (_flags[i].is_mandatory != false || BONUS == 1) { args[j++] = _flags[i].short_option; if (_flags[i].usage != NULL) args[j++] = ':'; } } DEBUG_LOG(args); struct option *options = _t_args_to_getopt_long(size); if (!options) { ERROR_LOG(strerror(ENOMEM)); exit(ENOMEM); } opterr = 1; int opt; while ((opt = getopt_long(argc, argv, args, options, NULL)) != -1) { switch (opt) { case 'v': INFO_LOG("argument verbose"); flags->verbose = true; break; case 'f': INFO_LOG("argument flood"); flags->flood = true; break; case 'n': INFO_LOG("argument no-reverse"); flags->reverse_dns = true; break; case 'c': INFO_LOG("argument count"); flags->count = check_num_arguments(optarg); break; case 'q': INFO_LOG("argument quiet"); flags->quiet = true; break; case 'w': INFO_LOG("argument wait"); flags->wait = check_num_arguments(optarg); break; case 'W': INFO_LOG("argument timeout"); flags->timeout = check_num_arguments(optarg); break; case '?': free(options); if (optopt != 0) { if (isprint(optopt)) { char invalid_option[2] = {optopt, 0}; WARN_LOG(invalid_option); } ERROR_LOG("Try 'ft_ping --help' or 'ft_ping --usage' for more information."); exit(64); } print_help(size); exit(EXIT_SUCCESS); default: if (strcmp(options[optind - 1].name, "usage")) print_usage(size); else { if (isprint(optopt)) { char invalid_option[2] = {optopt, 0}; WARN_LOG(invalid_option); } ERROR_LOG("Try 'ft_ping --help' or 'ft_ping --usage' for more information."); exit(64); } } } free(options); }