src/main.c

changeset 94
864f59271974
parent 92
84e0dec5db16
equal deleted inserted replaced
93:9b64437262a2 94:864f59271974
35 #include "colors.h" 35 #include "colors.h"
36 #include <string.h> 36 #include <string.h>
37 #include <time.h> 37 #include <time.h>
38 #include <getopt.h> 38 #include <getopt.h>
39 #include <locale.h> 39 #include <locale.h>
40 #include <sys/stat.h>
40 41
41 int get_settings(int argc, char **argv, Settings *settings) { 42 int get_settings(int argc, char **argv, Settings *settings) {
42 char *valid; 43 char *valid;
43 unsigned long int time, port; 44 unsigned long int time, port;
44 uint8_t timeunit = 60; 45 uint8_t timeunit = 60;
45 size_t len; 46 size_t len;
46 47 bool port_set = false;
47 for (int opt ; (opt = getopt(argc, argv, "a:bc:Fhp:rsS:t:Uv")) != -1 ;) { 48
49 for (int opt ; (opt = getopt(argc, argv, "a:bc:Fhp:rsS:t:uUv")) != -1 ;) {
48 switch (opt) { 50 switch (opt) {
49 case 'c': 51 case 'c':
50 settings->continuepgn = optarg; 52 settings->continuepgn = optarg;
51 break; 53 break;
52 case 'b': 54 case 'b':
58 case 's': 60 case 's':
59 settings->singlemachine = true; 61 settings->singlemachine = true;
60 break; 62 break;
61 case 'F': 63 case 'F':
62 settings->disableflip = true; 64 settings->disableflip = true;
65 break;
66 case 'u':
67 if (port_set) {
68 fprintf(stderr, "Cannot use Unix domain sockets "
69 "when a TCP port was specified.\n");
70 return 1;
71 }
72 settings->usedomainsocket = true;
63 break; 73 break;
64 case 'U': 74 case 'U':
65 settings->unicode = false; 75 settings->unicode = false;
66 break; 76 break;
67 case 't': 77 case 't':
85 settings->gameinfo.addtime = time; 95 settings->gameinfo.addtime = time;
86 } 96 }
87 } 97 }
88 break; 98 break;
89 case 'p': 99 case 'p':
100 if (port_set) {
101 fprintf(stderr, "Cannot use -p twice.\n");
102 return 1;
103 }
104 if (settings->usedomainsocket) {
105 fprintf(stderr, "Cannot specify TCP port "
106 "when using Unix domain sockets.\n");
107 return 1;
108 }
90 port = strtol(optarg, &valid, 10); 109 port = strtol(optarg, &valid, 10);
91 if (port < 1025 || port > 65535 || *valid != '\0') { 110 if (port < 1025 || port > 65535 || *valid != '\0') {
92 fprintf(stderr, 111 fprintf(stderr,
93 "Invalid port number (%s) - choose a number between " 112 "Invalid port number (%s) - choose a number between "
94 "1025 and 65535\n", 113 "1025 and 65535\n",
95 optarg); 114 optarg);
96 return 1; 115 return 1;
97 } else { 116 } else {
98 settings->port = (short) port; 117 settings->port = (short) port;
118 port_set = true;
99 } 119 }
100 break; 120 break;
101 case 'v': 121 case 'v':
102 printf("terminal-chess : Version %s (Netcode Version %d)\n", 122 printf("terminal-chess : Version %s (Netcode Version %d)\n",
103 PROGRAM_VERSION, NETCODE_VERSION); 123 PROGRAM_VERSION, NETCODE_VERSION);
109 "Starts/joins a network chess game\n" 129 "Starts/joins a network chess game\n"
110 "\nGeneral options\n" 130 "\nGeneral options\n"
111 " -c <PGN file> Continue the specified game\n" 131 " -c <PGN file> Continue the specified game\n"
112 " -h This help page\n" 132 " -h This help page\n"
113 " -p TCP port to use (default: 27015)\n" 133 " -p TCP port to use (default: 27015)\n"
134 " -u Use Unix domain socket instead of TCP\n"
114 " -U Disables unicode pieces\n" 135 " -U Disables unicode pieces\n"
115 " -v Print version information and exits\n" 136 " -v Print version information and exits\n"
116 "\nServer options\n" 137 "\nServer options\n"
117 " -a <time> Specifies the time to add after each move\n" 138 " -a <time> Specifies the time to add after each move\n"
118 " -b Server plays black pieces (default: white)\n" 139 " -b Server plays black pieces (default: white)\n"
119 " -r Distribute color randomly\n" 140 " -r Distribute color randomly\n"
120 " -t <time> Specifies time limit (default: no limit)\n" 141 " -t <time> Specifies time limit (default: no limit)\n"
121 "\nHot seat\n" 142 "\nHot seat\n"
122 " -s Play a hot seat game (no client/server)\n" 143 " -s Play a hot seat game (network options are ignored)\n"
123 " -F Do not automatically flip the board in hot seat games\n" 144 " -F Do not automatically flip the board in hot seat games\n"
124 "\nNotes\n" 145 "\nNotes\n"
125 "The time unit for -a is seconds and for -t minutes by default. To " 146 "The time unit for -a is seconds and for -t minutes by default. To "
126 "specify\nseconds for the -t option, use the s suffix.\n" 147 "specify\nseconds for the -t option, use the s suffix.\n"
127 "Example: -t 150s\n\n" 148 "Example: -t 150s\n\n"
128 "Use '-' for PGN files to read PGN data from standard input\n" 149 "Use '-' for PGN files to read PGN data from standard input\n\n"
150 "When playing over Unix domain socket, the HOST denotes the socket path.\n"
151 "When the path doest not exist, a game is created. Otherwise, the program\n"
152 "joins the existing game. When HOST is omitted, /tmp/chess.sock is used.\n"
129 ); 153 );
130 exit(0); 154 exit(0);
131 } 155 }
132 } 156 }
133 157
143 if (settings->serverhost) { 167 if (settings->serverhost) {
144 fprintf(stderr, "Can't continue a game when joining a server.\n"); 168 fprintf(stderr, "Can't continue a game when joining a server.\n");
145 return 1; 169 return 1;
146 } 170 }
147 } 171 }
172
173 if (settings->usedomainsocket) {
174 if (!settings->serverhost) {
175 settings->serverhost = "/tmp/chess.sock";
176 }
177 struct stat st;
178 if (stat(settings->serverhost, &st) == 0) {
179 if (S_ISSOCK(st.st_mode)) {
180 settings->ishost = false;
181 } else {
182 fprintf(stderr, "%s is not a Unix domain socket.\n",
183 settings->serverhost);
184 return 1;
185 }
186 } else {
187 settings->ishost = true;
188 }
189 } else {
190 settings->ishost = !settings->serverhost;
191 }
148 192
149 return 0; 193 return 0;
150 } 194 }
151 195
152 static Settings default_settings() { 196 static Settings settings;
153 Settings settings = {0}; 197
198 static void init_settings(void) {
199 memset(&settings, 0, sizeof(settings));
154 settings.gameinfo.servercolor = WHITE; 200 settings.gameinfo.servercolor = WHITE;
155 settings.port = 27015; 201 settings.port = 27015;
156 settings.unicode = !!setlocale(LC_CTYPE, "C.UTF-8"); 202 settings.unicode = !!setlocale(LC_CTYPE, "C.UTF-8");
157 return settings; 203 }
204
205 static void cleanup() {
206 endwin();
207 if (settings.usedomainsocket && settings.ishost) {
208 remove(settings.serverhost);
209 }
158 } 210 }
159 211
160 int main(int argc, char **argv) { 212 int main(int argc, char **argv) {
161 srand(time(NULL)); 213 srand(time(NULL));
162 214
163 Settings settings = default_settings(); 215 init_settings();
164 if (get_settings(argc, argv, &settings)) { 216 if (get_settings(argc, argv, &settings)) {
165 return 1; 217 return 1;
166 } 218 }
167 219
168 initscr(); 220 initscr();
175 } else { 227 } else {
176 fprintf(stderr, "Non-colored terminals are not supported yet."); 228 fprintf(stderr, "Non-colored terminals are not supported yet.");
177 endwin(); 229 endwin();
178 return EXIT_FAILURE; 230 return EXIT_FAILURE;
179 } 231 }
180 atexit((void(*)())endwin); 232 atexit(cleanup);
181 233
182 int exitcode; 234 int exitcode;
183 if (settings.singlemachine) { 235 if (settings.singlemachine) {
184 game_play_singlemachine(&settings); 236 game_play_singlemachine(&settings);
185 exitcode = EXIT_SUCCESS; 237 exitcode = EXIT_SUCCESS;
186 } else { 238 } else {
187 exitcode = is_server(&settings) ? 239 exitcode = settings.ishost ?
188 server_run(&settings) : client_run(&settings); 240 server_run(&settings) : client_run(&settings);
189 } 241 }
190 242
191 mvaddstr(getmaxy(stdscr)-1, 0, 243 mvaddstr(getmaxy(stdscr)-1, 0,
192 "Game has ended. Press any key to leave..."); 244 "Game has ended. Press any key to leave...");

mercurial