aboutsummaryrefslogtreecommitdiff
path: root/src/btasktd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/btasktd.c')
-rw-r--r--src/btasktd.c165
1 files changed, 165 insertions, 0 deletions
diff --git a/src/btasktd.c b/src/btasktd.c
new file mode 100644
index 0000000..a429e21
--- /dev/null
+++ b/src/btasktd.c
@@ -0,0 +1,165 @@
+/*-
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifndef BTASKTD_QUEUE_LEN
+# define QUEUE_LEN 16
+#endif
+
+enum flag_val_res {
+ fvr_not_found = -1,
+ fvr_min = fvr_not_found,
+ fvr_ok = 0,
+ fvr_invalid,
+ fvr_max = fvr_invalid
+};
+
+struct str_flag_val {
+ enum flag_val_res code;
+ char *data;
+};
+
+struct int_flag_val {
+ enum flag_val_res code;
+ int data;
+};
+
+/* -f the_str */
+static struct str_flag_val
+extract_str_flag(char flagletter, int argc, char **argv)
+{
+ struct str_flag_val res = {0};
+ char flagstr[3] = { '-', ' ', '\0' };
+ int i;
+ flagstr[1] = flagletter;
+ for (i = 1; i < argc; i++)
+ if (0 == strcmp(flagstr, argv[i]))
+ break;
+ if (i >= argc) {
+ res.code = fvr_not_found;
+ } else if (i == argc-1) {
+ res.code = fvr_invalid;
+ } else {
+ res.code = fvr_ok;
+ res.data = argv[i+1];
+ }
+ return res;
+}
+
+/* -f number */
+static struct int_flag_val
+extract_int_flag(char flagletter, int argc, char **argv)
+{
+ struct int_flag_val res;
+ struct str_flag_val strres =
+ extract_str_flag(flagletter, argc, argv);
+ char *endptr;
+ res.code = strres.code;
+ if (res.code != fvr_ok) {
+ return res;
+ }
+ res.data = strtol(strres.data, &endptr, 10);
+ if (*endptr != '\0')
+ res.code = fvr_invalid;
+ return res;
+}
+
+int
+main(int argc, char **argv)
+{
+ int server_fd, opt = 1, res, flags, port;
+ struct sockaddr_in addr = {0};
+ struct int_flag_val port_res =
+ extract_int_flag('p', argc, argv);
+ switch (port_res.code) {
+ case fvr_not_found:
+# ifdef BTASKTD_DEFAULT_PORT
+ port = BTASKTD_DEFAULT_PORT;
+# else
+ fputs("No port specified!\n", stderr);
+ return 1;
+# endif
+ break;
+ case fvr_invalid:
+ fputs("Invalid port!\n", stderr);
+ return 1;
+ case fvr_ok:
+ port = port_res.data;
+ }
+
+ server_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (server_fd < 0) {
+ 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);
+ perror("bind");
+ return 1;
+ }
+ res = listen(server_fd, QUEUE_LEN);
+ if (0 != res) {
+ close(server_fd);
+ perror("listen");
+ return 1;
+ }
+ res = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR,
+ &opt, sizeof(opt));
+ if (0 != res) {
+ close(server_fd);
+ perror("setsockopt");
+ return 1;
+ }
+ flags = fcntl(server_fd, F_GETFL);
+ fcntl(server_fd, F_SETFL, flags|O_NONBLOCK);
+
+ printf("btaskt server btasktd started on port %d\n", port);
+
+ /* main loop here */
+
+ printf("btaskt server btasktd stopped\n");
+ close(server_fd);
+ return 0;
+}