Added argument parser and set all logs to STDERR
This commit is contained in:
@@ -23,7 +23,7 @@ static struct epoll_event _evs[MAX_EPOLL_EVENTS];
|
||||
bool loop_init(loop_cb_t callback) {
|
||||
_efd = epoll_create1(0);
|
||||
if (_efd == -1) {
|
||||
printf("[!] epoll_create1 failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] epoll_create1 failed: %d\n", errno);
|
||||
return false;
|
||||
}
|
||||
_cb = callback;
|
||||
@@ -36,7 +36,7 @@ void loop_deinit() {
|
||||
|
||||
bool loop_ctl(int op, int fd, struct epoll_event *event) {
|
||||
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 true;
|
||||
@@ -50,7 +50,7 @@ bool loop_wait() {
|
||||
-1
|
||||
);
|
||||
if (result < 0) {
|
||||
printf("[!] epoll_wait failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] epoll_wait failed: %d\n", errno);
|
||||
return false;
|
||||
}
|
||||
if (!result) {
|
||||
|
||||
73
main.c
73
main.c
@@ -1,6 +1,8 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
@@ -9,6 +11,7 @@
|
||||
|
||||
#include "event_loop.h"
|
||||
#include "server.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Data
|
||||
@@ -20,6 +23,54 @@ static int _server_fd = -1;
|
||||
/*
|
||||
* 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.
|
||||
// Returns:
|
||||
// - true on success
|
||||
@@ -32,7 +83,7 @@ static bool signals_init() {
|
||||
sigaddset(&mask, SIGINT);
|
||||
sigaddset(&mask, SIGQUIT);
|
||||
if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) {
|
||||
printf("[!] sigprocmask failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] sigprocmask failed: %d\n", errno);
|
||||
return false;
|
||||
}
|
||||
_sig_fd = signalfd(
|
||||
@@ -41,7 +92,7 @@ static bool signals_init() {
|
||||
SFD_NONBLOCK
|
||||
);
|
||||
if (_sig_fd == -1) {
|
||||
printf("[!] signalfd failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] signalfd failed: %d\n", errno);
|
||||
return false;
|
||||
}
|
||||
struct epoll_event ev;
|
||||
@@ -54,7 +105,7 @@ static bool signals_init() {
|
||||
);
|
||||
if (!loop_res) {
|
||||
close(_sig_fd);
|
||||
printf("[!] loop_ctl failed\n");
|
||||
fprintf(stderr, "[!] loop_ctl failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -69,7 +120,7 @@ static void signals_deinit() {
|
||||
// Returns:
|
||||
// - true on success
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@@ -83,7 +134,7 @@ static bool server_init() {
|
||||
);
|
||||
if (!loop_res) {
|
||||
server_close();
|
||||
printf("[!] loop_ctl failed\n");
|
||||
fprintf(stderr, "[!] loop_ctl failed\n");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -106,16 +157,20 @@ static void on_fd_event(int fd, uint32_t events) {
|
||||
// Server event
|
||||
else if (fd == _server_fd) {
|
||||
if (!server_event(_server_fd)) {
|
||||
printf("[!] server_event failed\n");
|
||||
fprintf(stderr, "[!] server_event failed\n");
|
||||
_to_work = false;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
if (!parse_cli_args(argc, argv)) {
|
||||
print_usage_text();
|
||||
return 1;
|
||||
}
|
||||
if (!loop_init(on_fd_event)) {
|
||||
return 1;
|
||||
}
|
||||
@@ -131,10 +186,10 @@ int main(int argc, char **argv) {
|
||||
|
||||
while (_to_work) {
|
||||
if (!loop_wait()) {
|
||||
printf("[!] loop_wait returns false, stopping...\n");
|
||||
fprintf(stderr, "[!] loop_wait returns false, stopping...\n");
|
||||
break;
|
||||
}
|
||||
printf("--- loop ---\n");
|
||||
fprintf(stderr, "--- loop ---\n");
|
||||
}
|
||||
|
||||
server_close();
|
||||
|
||||
10
server.c
10
server.c
@@ -34,7 +34,7 @@ bool _accept() {
|
||||
int server_open(const char* host, int port) {
|
||||
struct hostent *he = gethostbyname(host);
|
||||
if (!he) {
|
||||
printf("[!] gethostbyname failed: %d (h_errno)\n", h_errno);
|
||||
fprintf(stderr, "[!] gethostbyname failed: %d (h_errno)\n", h_errno);
|
||||
return -1;
|
||||
}
|
||||
_fd = socket(
|
||||
@@ -43,13 +43,13 @@ int server_open(const char* host, int port) {
|
||||
IPPROTO_TCP
|
||||
);
|
||||
if (_fd == -1) {
|
||||
printf("[!] socket failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] socket failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
const int opt = 1;
|
||||
if (setsockopt(_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
|
||||
close(_fd);
|
||||
printf("[!] setsockopt failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] setsockopt failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
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);
|
||||
if (bind(_fd, (const void *)&addr, sizeof(addr)) == -1) {
|
||||
close(_fd);
|
||||
printf("[!] bind failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] bind failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
if (listen(_fd, LISTEN_BACKLOG) == -1) {
|
||||
close(_fd);
|
||||
printf("[!] listen failed: %d\n", errno);
|
||||
fprintf(stderr, "[!] listen failed: %d\n", errno);
|
||||
return -1;
|
||||
}
|
||||
return _fd;
|
||||
|
||||
75
utils.c
75
utils.c
@@ -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
23
utils.h
@@ -1,6 +1,29 @@
|
||||
#ifndef __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
|
||||
|
||||
Reference in New Issue
Block a user