Added argument parser and set all logs to STDERR

This commit is contained in:
Nikita Tyukalov, ASUS, Linux
2026-03-24 20:44:22 +03:00
parent 1cc2ef41d1
commit c8b0a5fe5a
5 changed files with 170 additions and 17 deletions

View File

@@ -23,7 +23,7 @@ static struct epoll_event _evs[MAX_EPOLL_EVENTS];
bool loop_init(loop_cb_t callback) { bool loop_init(loop_cb_t callback) {
_efd = epoll_create1(0); _efd = epoll_create1(0);
if (_efd == -1) { if (_efd == -1) {
printf("[!] epoll_create1 failed: %d\n", errno); fprintf(stderr, "[!] epoll_create1 failed: %d\n", errno);
return false; return false;
} }
_cb = callback; _cb = callback;
@@ -36,7 +36,7 @@ void loop_deinit() {
bool loop_ctl(int op, int fd, struct epoll_event *event) { bool loop_ctl(int op, int fd, struct epoll_event *event) {
if (epoll_ctl(_efd, op, fd, event) == -1) { if (epoll_ctl(_efd, op, fd, event) == -1) {
printf("[!] epoll_ctl failed: %d\n", errno); fprintf(stderr, "[!] epoll_ctl failed: %d\n", errno);
return false; return false;
} }
return true; return true;
@@ -50,7 +50,7 @@ bool loop_wait() {
-1 -1
); );
if (result < 0) { if (result < 0) {
printf("[!] epoll_wait failed: %d\n", errno); fprintf(stderr, "[!] epoll_wait failed: %d\n", errno);
return false; return false;
} }
if (!result) { if (!result) {

73
main.c
View File

@@ -1,6 +1,8 @@
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
@@ -9,6 +11,7 @@
#include "event_loop.h" #include "event_loop.h"
#include "server.h" #include "server.h"
#include "utils.h"
/* /*
* Data * Data
@@ -20,6 +23,54 @@ static int _server_fd = -1;
/* /*
* Private API * Private API
*/ */
// Parse command line arguments and check if mandatory ones are present.
// Parameters:
// - argc
// - argv
// Returns:
// - true on success
// - false on failure
bool parse_cli_args(int argc, char** argv) {
if (argc < 2) {
return false;
}
int key_length, value_length;
int i = 1;
char first_sym;
while (i < argc) {
key_length = strlen(argv[i] + 1);
first_sym = argv[i][0];
if (key_length != 1 || (first_sym != '+' && first_sym != '-')) {
fprintf(stderr, "[!] Argument '%s' is discarded\n", argv[i]);
return false;
}
// flag
if (first_sym == '+') {
cli_arg_set(argv[i] + 1, argv[i] + 1);
i++;
continue;
}
// argument
if (i + 1 >= argc) {
fprintf(stderr, "[!] Argument '%s' misses a value\n", argv[i]);
return false;
}
value_length = strlen(argv[i + 1]);
if (value_length < 1) {
fprintf(stderr, "[!] Argument '%s' has empty value\n", argv[i]);
return false;
}
cli_arg_set(argv[i] + 1, argv[i + 1]);
i += 2;
}
bool required_args_present = true;
required_args_present &= cli_arg_get("M") ? true : false;
required_args_present &= cli_arg_get("A") ? true : false;
required_args_present &= cli_arg_get("P") ? true : false;
required_args_present &= cli_arg_get("E") ? true : false;
return required_args_present;
}
// Initialize signals. // Initialize signals.
// Returns: // Returns:
// - true on success // - true on success
@@ -32,7 +83,7 @@ static bool signals_init() {
sigaddset(&mask, SIGINT); sigaddset(&mask, SIGINT);
sigaddset(&mask, SIGQUIT); sigaddset(&mask, SIGQUIT);
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) { if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
printf("[!] sigprocmask failed: %d\n", errno); fprintf(stderr, "[!] sigprocmask failed: %d\n", errno);
return false; return false;
} }
_sig_fd = signalfd( _sig_fd = signalfd(
@@ -41,7 +92,7 @@ static bool signals_init() {
SFD_NONBLOCK SFD_NONBLOCK
); );
if (_sig_fd == -1) { if (_sig_fd == -1) {
printf("[!] signalfd failed: %d\n", errno); fprintf(stderr, "[!] signalfd failed: %d\n", errno);
return false; return false;
} }
struct epoll_event ev; struct epoll_event ev;
@@ -54,7 +105,7 @@ static bool signals_init() {
); );
if (!loop_res) { if (!loop_res) {
close(_sig_fd); close(_sig_fd);
printf("[!] loop_ctl failed\n"); fprintf(stderr, "[!] loop_ctl failed\n");
return false; return false;
} }
return true; return true;
@@ -69,7 +120,7 @@ static void signals_deinit() {
// Returns: // Returns:
// - true on success // - true on success
static bool server_init() { static bool server_init() {
_server_fd = server_open("0.0.0.0", 20070); _server_fd = server_open(cli_arg_get("A"), atoi(cli_arg_get("P")));
if (_server_fd == -1) { if (_server_fd == -1) {
return false; return false;
} }
@@ -83,7 +134,7 @@ static bool server_init() {
); );
if (!loop_res) { if (!loop_res) {
server_close(); server_close();
printf("[!] loop_ctl failed\n"); fprintf(stderr, "[!] loop_ctl failed\n");
return false; return false;
} }
return true; return true;
@@ -106,16 +157,20 @@ static void on_fd_event(int fd, uint32_t events) {
// Server event // Server event
else if (fd == _server_fd) { else if (fd == _server_fd) {
if (!server_event(_server_fd)) { if (!server_event(_server_fd)) {
printf("[!] server_event failed\n"); fprintf(stderr, "[!] server_event failed\n");
_to_work = false; _to_work = false;
} }
} }
else { else {
printf("[!] Event has happened on an unknown file descriptor\n"); fprintf(stderr, "[!] Event has happened on an unknown file descriptor\n");
} }
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
if (!parse_cli_args(argc, argv)) {
print_usage_text();
return 1;
}
if (!loop_init(on_fd_event)) { if (!loop_init(on_fd_event)) {
return 1; return 1;
} }
@@ -131,10 +186,10 @@ int main(int argc, char **argv) {
while (_to_work) { while (_to_work) {
if (!loop_wait()) { if (!loop_wait()) {
printf("[!] loop_wait returns false, stopping...\n"); fprintf(stderr, "[!] loop_wait returns false, stopping...\n");
break; break;
} }
printf("--- loop ---\n"); fprintf(stderr, "--- loop ---\n");
} }
server_close(); server_close();

View File

@@ -34,7 +34,7 @@ bool _accept() {
int server_open(const char* host, int port) { int server_open(const char* host, int port) {
struct hostent *he = gethostbyname(host); struct hostent *he = gethostbyname(host);
if (!he) { if (!he) {
printf("[!] gethostbyname failed: %d (h_errno)\n", h_errno); fprintf(stderr, "[!] gethostbyname failed: %d (h_errno)\n", h_errno);
return -1; return -1;
} }
_fd = socket( _fd = socket(
@@ -43,13 +43,13 @@ int server_open(const char* host, int port) {
IPPROTO_TCP IPPROTO_TCP
); );
if (_fd == -1) { if (_fd == -1) {
printf("[!] socket failed: %d\n", errno); fprintf(stderr, "[!] socket failed: %d\n", errno);
return -1; return -1;
} }
const int opt = 1; const int opt = 1;
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) { if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
close(_fd); close(_fd);
printf("[!] setsockopt failed: %d\n", errno); fprintf(stderr, "[!] setsockopt failed: %d\n", errno);
return -1; return -1;
} }
struct sockaddr_in addr; struct sockaddr_in addr;
@@ -58,12 +58,12 @@ int server_open(const char* host, int port) {
memcpy(&addr.sin_addr, he->h_addr, he->h_length); memcpy(&addr.sin_addr, he->h_addr, he->h_length);
if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) { if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) {
close(_fd); close(_fd);
printf("[!] bind failed: %d\n", errno); fprintf(stderr, "[!] bind failed: %d\n", errno);
return -1; return -1;
} }
if (listen(_fd, LISTEN_BACKLOG) == -1) { if (listen(_fd, LISTEN_BACKLOG) == -1) {
close(_fd); close(_fd);
printf("[!] listen failed: %d\n", errno); fprintf(stderr, "[!] listen failed: %d\n", errno);
return -1; return -1;
} }
return _fd; return _fd;

75
utils.c
View File

@@ -0,0 +1,75 @@
#include "utils.h"
#include <stdio.h>
#include <stddef.h>
#include <string.h>
/*
* Macros
*/
#define MAX_CLI_ARGS (20)
/*
* Type definitions
*/
typedef struct {
const char *key;
char *value;
} cli_arg_t;
/*
* Data
*/
static cli_arg_t _cli_args[MAX_CLI_ARGS];
/*
* Public API
*/
void print_usage_text() {
printf("ipoim -M <mode> -A <address> -P <port> -C <carrier> ...\n");
printf(" --- MANDATORY ARGUMENTS ---\n");
printf(" -M <mode> - operation mode ('provider' or 'last-mile')\n");
printf(" -A <address> - IPv4 to listen on/connect to\n");
printf(" -P <port> - port to listen on/connect to\n");
printf(" -E <carrier> - extension to use, one of:\n");
printf(" * pipe - use STDIN and STDOUT\n");
printf(" --- OPTIONAL ARGUMENTS ---\n");
printf(" +V - be verbose\n");
}
bool cli_arg_set(const char *key, char *value) {
int index_to_use = -1;
for (int i = 0; i < MAX_CLI_ARGS; ++i) {
// empty entry
if (_cli_args[i].key == NULL) {
// update index only if no place is found yet
if (index_to_use == -1)
index_to_use = i;
}
// entry with the same name
else if (!strcmp(_cli_args[i].key, key)) {
index_to_use = i;
break;
}
}
// no space for the argument
if (index_to_use == -1) {
return false;
}
_cli_args[index_to_use].key = key;
_cli_args[index_to_use].value = value;
return true;
}
const char *cli_arg_get(const char *key) {
for (int i = 0; i < MAX_CLI_ARGS; ++i) {
if (_cli_args[i].key == NULL) {
continue;
}
if (strcmp(_cli_args[i].key, key)) {
continue;
}
return _cli_args[i].value;
}
return NULL;
}

23
utils.h
View File

@@ -1,6 +1,29 @@
#ifndef __UTILS_H #ifndef __UTILS_H
#define __UTILS_H #define __UTILS_H
#include <stdbool.h>
// Print usage text.
void print_usage_text();
// Set CLI argument.
// Parameters:
// - key - argument key (without leading dash)
// - value - argument value as string
// Returns:
// - true on success
// - false on failure
// Remarks:
// - neither key nor value are copied, they are saved as pointers
// - use this function only with data from argv
bool cli_arg_set(const char *key, char *value);
// Get CLI argument.
// Parameters:
// - key - argument key (without leading dash)
// Returns:
// - pointer to the value (not owned by you)
// - NULL on failure
const char *cli_arg_get(const char *key);
#endif #endif