src/main.c

changeset 94
864f59271974
parent 92
84e0dec5db16
--- a/src/main.c	Sun Mar 29 13:26:00 2026 +0200
+++ b/src/main.c	Sun Mar 29 15:17:28 2026 +0200
@@ -37,14 +37,16 @@
 #include <time.h>
 #include <getopt.h>
 #include <locale.h>
+#include <sys/stat.h>
 
 int get_settings(int argc, char **argv, Settings *settings) {
     char *valid;
     unsigned long int time, port;
     uint8_t timeunit = 60;
     size_t len;
+    bool port_set = false;
     
-    for (int opt ; (opt = getopt(argc, argv, "a:bc:Fhp:rsS:t:Uv")) != -1 ;) {
+    for (int opt ; (opt = getopt(argc, argv, "a:bc:Fhp:rsS:t:uUv")) != -1 ;) {
         switch (opt) {
         case 'c':
             settings->continuepgn = optarg;
@@ -61,6 +63,14 @@
         case 'F':
             settings->disableflip = true;
             break;
+        case 'u':
+            if (port_set) {
+                fprintf(stderr, "Cannot use Unix domain sockets "
+                        "when a TCP port was specified.\n");
+                return 1;
+            }
+            settings->usedomainsocket = true;
+            break;
         case 'U':
             settings->unicode = false;
             break;
@@ -87,6 +97,15 @@
             }
             break;
         case 'p':
+            if (port_set) {
+                fprintf(stderr, "Cannot use -p twice.\n");
+                return 1;
+            }
+            if (settings->usedomainsocket) {
+                fprintf(stderr, "Cannot specify TCP port "
+                        "when using Unix domain sockets.\n");
+                return 1;
+            }
             port = strtol(optarg, &valid, 10);
             if (port < 1025 || port > 65535 || *valid != '\0') {
                 fprintf(stderr,
@@ -96,6 +115,7 @@
                 return 1;
             } else {
                 settings->port = (short) port;
+                port_set = true;
             }
             break;
         case 'v':
@@ -111,6 +131,7 @@
 "  -c <PGN file> Continue the specified game\n"
 "  -h            This help page\n"
 "  -p            TCP port to use (default: 27015)\n"
+"  -u            Use Unix domain socket instead of TCP\n"
 "  -U            Disables unicode pieces\n"
 "  -v            Print version information and exits\n"
 "\nServer options\n"
@@ -119,13 +140,16 @@
 "  -r            Distribute color randomly\n"
 "  -t <time>     Specifies time limit (default: no limit)\n"
 "\nHot seat\n"
-"  -s            Play a hot seat game (no client/server)\n"
+"  -s            Play a hot seat game (network options are ignored)\n"
 "  -F            Do not automatically flip the board in hot seat games\n"
 "\nNotes\n"
 "The time unit for -a is seconds and for -t minutes by default. To "
 "specify\nseconds for the -t option, use the s suffix.\n"
 "Example: -t 150s\n\n"
-"Use '-' for PGN files to read PGN data from standard input\n"
+"Use '-' for PGN files to read PGN data from standard input\n\n"
+"When playing over Unix domain socket, the HOST denotes the socket path.\n"
+"When the path doest not exist, a game is created. Otherwise, the program\n"
+"joins the existing game. When HOST is omitted, /tmp/chess.sock is used.\n"
             );
             exit(0);
         }
@@ -145,22 +169,50 @@
             return 1;
         }
     }
+
+    if (settings->usedomainsocket) {
+        if (!settings->serverhost) {
+            settings->serverhost = "/tmp/chess.sock";
+        }
+        struct stat st;
+        if (stat(settings->serverhost, &st) == 0) {
+            if (S_ISSOCK(st.st_mode)) {
+                settings->ishost = false;
+            } else {
+                fprintf(stderr, "%s is not a Unix domain socket.\n",
+                    settings->serverhost);
+                return 1;
+            }
+        } else {
+            settings->ishost = true;
+        }
+    } else {
+        settings->ishost = !settings->serverhost;
+    }
     
     return 0;
 }
 
-static Settings default_settings() {
-    Settings settings = {0};
+static Settings settings;
+
+static void init_settings(void) {
+    memset(&settings, 0, sizeof(settings));
     settings.gameinfo.servercolor = WHITE;
     settings.port = 27015;
     settings.unicode = !!setlocale(LC_CTYPE, "C.UTF-8");
-    return settings;
+}
+
+static void cleanup() {
+    endwin();
+    if (settings.usedomainsocket && settings.ishost) {
+        remove(settings.serverhost);
+    }
 }
 
 int main(int argc, char **argv) {
     srand(time(NULL));
-    
-    Settings settings = default_settings();
+
+    init_settings();
     if (get_settings(argc, argv, &settings)) {
         return 1;
     }
@@ -177,14 +229,14 @@
         endwin();
         return EXIT_FAILURE;
     }
-    atexit((void(*)())endwin);
+    atexit(cleanup);
     
     int exitcode;
     if (settings.singlemachine) {
         game_play_singlemachine(&settings);
         exitcode = EXIT_SUCCESS;
     } else {
-        exitcode = is_server(&settings) ?
+        exitcode = settings.ishost ?
             server_run(&settings) : client_run(&settings);
     }
     

mercurial