Fix buffer overrun during loadding opening names
[capablanca.git] / lasker-2.2.3 / src / timeseal.c
1 /* 
2    Copyright 2002 Andrew Tridgell <tridge@samba.org>
3    
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2 of the License, or
7    (at your option) any later version.
8    
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13    
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   
17  */
18
19 /*   glue code that connects the chess server to the external timeseal
20  *   decoder */
21
22 #include "includes.h"
23
24 /*
25   send a string to the decoder sub-process and return the modified (decoded) string 
26   the return value is the decoded timestamp. It will be zero if the decoder didn't
27   recognise the input as valid timeseal data
28  */
29 static unsigned decode(unsigned char *s)
30 {
31         char line[1024];
32         char *p;
33         unsigned t = 0;
34
35         snprintf(line, 1000, "%s", s); // [HGM] limit length to 1000, to prevent crashing timeseal decoder
36   
37         /* send the encoded data to the decoder process */
38         dprintf(timeseal_globals.decoder_conn, "%s\n", line);
39         
40         if (!fd_gets(line, sizeof(line), timeseal_globals.decoder_conn)) {
41                 d_printf("Bad result from timeseal decoder? (t=%u)\n", t);
42                 close(timeseal_globals.decoder_conn);
43                 timeseal_globals.decoder_conn = -1;
44                 return 0;
45         }
46         line[strlen(line)-1] = 0;
47
48         p = strchr(line, ':');
49         if (!p) {
50                 d_printf("Badly formed timeseal decoder line: [%s]\n", line);
51                 close(timeseal_globals.decoder_conn);
52                 timeseal_globals.decoder_conn = -1;
53                 return 0;
54         }
55         
56         t = atoi(line);
57         strcpy(s, p+2);
58         
59         return t;
60 }
61
62 /* 
63    initialise the timeseal decoder sub-process
64 */
65 void timeseal_init(const char *path)
66 {
67         int fd[2];
68         pid_t pid;
69         
70         /* use a socketpair to get a bi-directional pipe with large buffers */
71         if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0) {
72                 d_printf("Failed to create socket pair!\n");
73                 exit(1);
74         }
75         
76         pid = fork();
77         
78         if (pid == 0) {
79                 close(fd[1]);
80                 close(0);
81                 close(1);
82                 close(2);
83                 dup2(fd[0], 0);
84                 dup2(fd[0], 1);
85                 open("/dev/null", O_WRONLY); /* stderr */
86                 execl(path, "[timeseal]", NULL);
87                 exit(1);
88         }
89         
90         timeseal_globals.decoder_conn = fd[1];
91         close(fd[0]);
92 }
93
94
95 /* 
96    parse a command line from a user on *con that may be timeseal encoded. 
97    return 1 if the command should be processed further, 0 if the command
98    should be discarded
99  */
100 int timeseal_parse(char *command, struct connection_t *con)
101 {
102         unsigned t;
103         
104         /* do we have a decoder sub-process? */
105         if (timeseal_globals.decoder_conn <= 0) return 1;
106         
107         /* are they using timeseal on this connection? */
108         if (!con->timeseal_init && !con->timeseal) return 1;
109         
110         t = decode(command);
111         
112         if (t == 0) {
113                 /* this wasn't encoded using timeseal */
114                 d_printf("Non-timeseal data [%s]\n", command);
115                 con->timeseal_init = 0;
116                 return 1;
117         }
118         
119         if (con->timeseal_init) {
120                 con->timeseal_init = 0;
121                 con->timeseal = 1;
122                 d_printf("Connected with timeseal %s\n", command);
123                 if (strncmp(command, "TIMESTAMP|", 10) == 0) {
124                         return 0;
125                 }
126         }
127         
128         con->time = t;
129         
130         /* now check for the special move time tag */
131         if (strcmp(command, "\ 29") == 0) {
132                 int p = player_find(con->fd);
133                 struct player *pp = &player_globals.parray[p];
134                 if (p >= 0 && pp->game >= 0) {
135                         int g = pp->game;
136                         if (game_globals.garray[g].game_state.onMove != 
137                             pp->side) {
138                                 return 0;
139                         }
140                         if (pp->side == WHITE) {
141                                 if (game_globals.garray[g].wTimeWhenReceivedMove == 0) {
142                                         game_globals.garray[g].wTimeWhenReceivedMove = t;
143                                 }
144                         } else {
145                                 if (game_globals.garray[g].bTimeWhenReceivedMove == 0) {
146                                         game_globals.garray[g].bTimeWhenReceivedMove = t;
147                                 }
148                         }
149                         if (game_globals.garray[g].flag_pending != FLAG_NONE) {
150                                 ExecuteFlagCmd(p, net_globals.con[pp->socket]);
151                         }
152                 }
153                 /* we have processed this special tag - don't process it further */
154                 return 0;
155         }
156         
157         return 1;
158 }
159
160 /*
161   used to call flag on players with timeseal
162  */
163 void ExecuteFlagCmd(int p, struct connection_t *con)
164 {
165         struct player *pp = &player_globals.parray[p];
166         struct game *gg;
167
168         if (pp->game == -1) {
169                 return;
170         }
171
172         gg = &game_globals.garray[pp->game];
173
174         if (pp->side == WHITE) {
175                 gg->wRealTime -= con->time - gg->wTimeWhenReceivedMove;
176                 gg->wTimeWhenReceivedMove = con->time;
177                 if (gg->wRealTime < 0) {
178                         pcommand(pp->opponent, "flag");
179                 }
180         } else if (pp->side == BLACK) {
181                 gg->bRealTime -= con->time - gg->bTimeWhenReceivedMove;
182                 gg->bTimeWhenReceivedMove = con->time;
183                 if (gg->bRealTime < 0) {
184                         pcommand(pp->opponent, "flag");
185                 }
186         }
187
188         game_update_time(pp->game);
189         gg->flag_pending = FLAG_NONE;
190 }