13 #include <sys/types.h>
\r
14 #include <sys/resource.h>
\r
25 static const unsigned int StringSize = 4096;
\r
33 static void my_close (int fd);
\r
34 static void my_dup2 (int old_fd, int new_fd);
\r
40 bool engine_is_ok(const engine_t * engine) {
\r
42 if (engine == NULL) return false;
\r
44 if (!io_is_ok(engine->io)) return false;
\r
51 void engine_open(engine_t * engine) {
\r
53 const char * dir, * command;
\r
54 char string[StringSize];
\r
58 int from_engine[2], to_engine[2];
\r
61 ASSERT(engine!=NULL);
\r
65 dir = option_get_string("EngineDir");
\r
66 my_log("POLYGLOT Dir \"%s\"\n",dir);
\r
68 command = option_get_string("EngineCommand");
\r
69 my_log("POLYGLOT Command \"%s\"\n",command);
\r
71 // parse the command line and create the argument list
\r
73 if (strlen(command) >= StringSize) my_fatal("engine_open(): buffer overflow\n");
\r
74 strcpy(string,command);
\r
78 for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {
\r
86 if (pipe(from_engine) == -1) {
\r
87 my_fatal("engine_open(): pipe(): %s\n",strerror(errno));
\r
90 if (pipe(to_engine) == -1) {
\r
91 my_fatal("engine_open(): pipe(): %s\n",strerror(errno));
\r
94 // create the child process
\r
100 my_fatal("engine_open(): fork(): %s\n",strerror(errno));
\r
102 } else if (pid == 0) {
\r
106 // close unused pipe descriptors to avoid deadlocks
\r
108 my_close(from_engine[0]);
\r
109 my_close(to_engine[1]);
\r
111 // attach the pipe to standard input
\r
113 my_dup2(to_engine[0],STDIN_FILENO);
\r
114 my_close(to_engine[0]);
\r
116 // attach the pipe to standard output
\r
118 my_dup2(from_engine[1],STDOUT_FILENO);
\r
119 my_close(from_engine[1]);
\r
121 // attach standard error to standard output
\r
123 my_dup2(STDOUT_FILENO,STDERR_FILENO);
\r
125 // set a low priority
\r
127 if (option_get_bool("UseNice")) {
\r
128 my_log("POLYGLOT Adjust Engine Piority");
\r
129 nice(option_get_int("NiceValue"));
\r
132 // change the current directory
\r
134 if (dir[0] != '\0' && chdir(dir) == -1) {
\r
135 my_fatal("engine_open(): chdir(): %s\n",strerror(errno));
\r
138 // launch the new executable file
\r
140 execvp(argv[0],&argv[0]);
\r
142 // execvp() only returns when an error has occured
\r
144 my_fatal("engine_open(): execvp(): %s\n",strerror(errno));
\r
146 } else { // pid > 0
\r
150 // parent = PolyGlot
\r
152 // close unused pipe descriptors to avoid deadlocks
\r
154 my_close(from_engine[1]);
\r
155 my_close(to_engine[0]);
\r
157 // fill in the engine struct
\r
159 engine->io->in_fd = from_engine[0];
\r
160 engine->io->out_fd = to_engine[1];
\r
161 engine->io->name = "Engine";
\r
163 engine->state|=ENGINE_ACTIVE; // can we test if this really true?
\r
165 io_init(engine->io);
\r
171 bool engine_active(engine_t *engine){
\r
172 return (engine->state & ENGINE_ACTIVE)!=0;
\r
177 bool engine_eof(engine_t *engine){
\r
178 return (engine->state & ENGINE_EOF)!=0;
\r
181 // engine_set_nice_value()
\r
183 void engine_set_nice_value(engine_t * engine, int value){
\r
184 setpriority(PRIO_PROCESS,engine->pid,value);
\r
190 void engine_close(engine_t * engine) {
\r
192 ASSERT(engine_is_ok(engine));
\r
194 char string[StringSize];
\r
195 io_close(engine->io);
\r
197 while (!engine_eof(engine)) {
\r
198 engine_get(engine,string,StringSize);
\r
203 // engine_get_non_blocking()
\r
205 bool engine_get_non_blocking(engine_t * engine, char string[], int size){
\r
206 if(io_line_ready(engine->io)){
\r
207 engine_get(engine,string,StringSize);
\r
217 void engine_get(engine_t * engine, char string[], int size) {
\r
219 ASSERT(engine_is_ok(engine));
\r
220 ASSERT(string!=NULL);
\r
223 while (!io_line_ready(engine->io)) {
\r
224 io_get_update(engine->io);
\r
227 if (!io_get_line(engine->io,string,size)) { // EOF
\r
228 engine->state|=ENGINE_EOF;
\r
234 void engine_send(engine_t * engine, const char format[], ...) {
\r
237 char string[StringSize];
\r
239 ASSERT(engine_is_ok(engine));
\r
240 ASSERT(format!=NULL);
\r
244 va_start(arg_list,format);
\r
245 vsprintf(string,format,arg_list);
\r
250 io_send(engine->io,"%s",string);
\r
253 // engine_send_queue()
\r
255 void engine_send_queue(engine_t * engine, const char format[], ...) {
\r
258 char string[StringSize];
\r
260 ASSERT(engine_is_ok(engine));
\r
261 ASSERT(format!=NULL);
\r
265 va_start(arg_list,format);
\r
266 vsprintf(string,format,arg_list);
\r
271 io_send_queue(engine->io,"%s",string);
\r
276 static void my_close(int fd) {
\r
280 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
\r
285 static void my_dup2(int old_fd, int new_fd) {
\r
290 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));
\r
293 // end of posix part
\r
300 #include <stdlib.h>
\r
301 #include <string.h>
\r
302 #include <windows.h>
\r
303 #include <direct.h>
\r
307 #include "engine.h"
\r
308 #include "option.h"
\r
314 static const int StringSize = 4096;
\r
318 static int nQueuePtr = 0;
\r
319 static char szQueueString[StringSize];
\r
320 engine_t Engine[1];
\r
324 void set_affinity(engine_t *engine, int affin){
\r
325 if(affin==-1) return;
\r
327 typedef void (WINAPI *SPAM)(HANDLE, int);
\r
329 pSPAM = (SPAM) GetProcAddress(
\r
330 GetModuleHandle(TEXT("kernel32.dll")),
\r
331 "SetProcessAffinityMask");
\r
333 // [HGM] avoid crash on Win95 by first checking if API call exists
\r
334 my_log("POLYGLOT Setting process affinity to %d\n",affin);
\r
335 pSPAM((engine->io).hProcess,affin);
\r
337 my_log("POLYGLOT API call \"SetProcessAffinityMask\" not available\n");
\r
341 DWORD GetWin32Priority(int nice)
\r
344 REALTIME_PRIORITY_CLASS 0x00000100
\r
345 HIGH_PRIORITY_CLASS 0x00000080
\r
346 ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
\r
347 NORMAL_PRIORITY_CLASS 0x00000020
\r
348 BELOW_NORMAL_PRIORITY_CLASS 0x00004000
\r
349 IDLE_PRIORITY_CLASS 0x00000040
\r
351 if (nice < -15) return 0x00000080;
\r
352 if (nice < 0) return 0x00008000;
\r
353 if (nice == 0) return 0x00000020;
\r
354 if (nice < 15) return 0x00004000;
\r
358 void engine_set_nice_value(engine_t *engine, int value){
\r
359 SetPriorityClass((engine->io).hProcess,
\r
360 GetWin32Priority(value));
\r
363 void engine_send_queue(engine_t * engine,const char *szFormat, ...) {
\r
364 nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
367 void engine_send(engine_t * engine, const char *szFormat, ...) {
\r
368 vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
369 (engine->io).LineOutput(szQueueString);
\r
370 my_log("Adapter->Engine: %s\n",szQueueString);
\r
374 void engine_close(engine_t * engine){
\r
375 char string[StringSize];
\r
376 (engine->io).Close();
\r
378 while (!engine_eof(engine)) {
\r
379 engine_get(Engine,string,StringSize);
\r
381 (engine->io).Kill();
\r
384 void engine_open(engine_t * engine){
\r
388 if( (my_dir = _getcwd( NULL, 0 )) == NULL )
\r
389 my_fatal("Can't build path: %s\n",strerror(errno));
\r
390 SetCurrentDirectory(option_get_string("EngineDir"));
\r
391 (engine->io).Open(option_get_string("EngineCommand"));
\r
392 if((engine->io).Active()){
\r
393 engine->state|=ENGINE_ACTIVE;
\r
394 //play with affinity (bad idea)
\r
395 affinity=option_get_int("Affinity");
\r
396 if(affinity!=-1) set_affinity(engine,affinity); //AAA
\r
398 SetCurrentDirectory(my_dir);
\r
399 // set a low priority
\r
400 if (option_get_bool("UseNice")){
\r
401 my_log("POLYGLOT Adjust Engine Piority\n");
\r
402 engine_set_nice_value(engine, option_get_int("NiceValue"));
\r
408 bool engine_active(engine_t *engine){
\r
409 return (engine->state & ENGINE_ACTIVE)!=0;
\r
412 bool engine_eof(engine_t *engine){
\r
413 return (engine->state & ENGINE_EOF)!=0;
\r
416 bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){
\r
417 if(engine_eof(engine)){ return false;}
\r
418 if ((engine->io).GetBuffer(szLineStr)) {
\r
419 my_log("Engine->Adapter: %s\n",szLineStr);
\r
423 if(engine->io.EOF_()){
\r
424 engine->state|=ENGINE_EOF;
\r
425 my_log("POLYGLOT *** EOF from Engine ***\n");
\r
431 void engine_get(engine_t * engine, char *szLineStr, int size){
\r
432 (engine->io).LineInput(szLineStr);
\r
433 if(engine->io.EOF_()){
\r
434 engine->state|=ENGINE_EOF;
\r
435 my_log("POLYGLOT *** EOF from Engine ***\n");
\r
437 my_log("Engine->Adapter: %s\n",szLineStr);
\r