/*- * Copyright (c) 2026, Mr. Goblin * * SPDX-License-Identifier: BSD-2-Clause * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include "cliflags.h" #define BTASKTD_HELP_STR \ "Copyright (c) 2026, Mr. Goblin\n" \ "btasktd - task tracking TCP-server\n" \ "Usage: btasktd [-Vh] [-p port] [-u users]\n" \ "For more info read program's man page\n" #define BTASKTD_VERSION_STR \ "0.0.0" #ifndef BTASKTD_QUEUE_LEN # define BTASKTD_QUEUE_LEN 16 #endif static void fprint_help(FILE *f) { fputs(BTASKTD_HELP_STR, f); } static void set_nonblock(int fd) { int fflags = fcntl(fd, F_GETFL); fcntl(fd, F_SETFL, fflags|O_NONBLOCK); } int main(int argc, char **argv) { int server_fd, opt = 1, res, port, passed_flags = 1, users_cnt; int *users = NULL; struct sockaddr_in addr = {0}; struct int_flag_val int_res; struct bool_flag_val show_ver, show_help; show_ver = extract_bool_flag('V', argc, argv); if (fvr_ok == show_ver.code && show_ver.data) { printf("btasktd version %s\n", BTASKTD_VERSION_STR); return 0; } show_help = extract_bool_flag('h', argc, argv); if (show_help.code == fvr_ok && show_help.data) { fprint_help(stdout); return 0; } int_res = extract_int_flag('p', argc, argv); switch (int_res.code) { case fvr_not_found: # ifdef BTASKTD_DEFAULT_PORT port = BTASKTD_DEFAULT_PORT; # else fputs("No port specified!\n", stderr); passed_flags = 0; # endif break; case fvr_ok: port = int_res.data; if (port > 0) break; /* fallthrough */ case fvr_invalid: fputs("Invalid port!\n", stderr); return 1; break; } int_res = extract_int_flag('u', argc, argv); switch (int_res.code) { case fvr_not_found: # ifdef BTASKTD_DEFAULT_USERS_CNT users_cnt = BTASKTD_DEFAULT_USERS_CNT; # else fputs("No users count specified!\n", stderr); passed_flags = 0; # endif break; case fvr_ok: users_cnt = int_res.data; if (users_cnt > 0) break; /* fallthrough */ case fvr_invalid: fputs("Invalid users count!\n", stderr); return 1; break; } if (!passed_flags) { fputs("-\n", stderr); fprint_help(stderr); return 1; } users = (int*)malloc(users_cnt * sizeof(int)); if (NULL == users) { fputs("No memory!\n", stderr); return 1; } server_fd = socket(AF_INET, SOCK_STREAM, 0); if (server_fd < 0) { free(users); perror("socket"); return 1; } addr.sin_family = AF_INET; addr.sin_port = htons(port); addr.sin_addr.s_addr = htonl(INADDR_ANY); res = bind(server_fd, (struct sockaddr*)&addr, sizeof(addr)); if (0 != res) { close(server_fd); free(users); perror("bind"); return 1; } res = listen(server_fd, BTASKTD_QUEUE_LEN); if (0 != res) { close(server_fd); free(users); perror("listen"); return 1; } res = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); if (0 != res) { close(server_fd); free(users); perror("setsockopt"); return 1; } set_nonblock(server_fd); printf("btaskt server btasktd started on port %d\n", port); /* main loop here */ printf("btaskt server btasktd stopped\n"); close(server_fd); free(users); return 0; }