13 #include <sys/types.h>
\r
24 static const int StringSize = 4096;
\r
32 static void my_close (int fd);
\r
33 static void my_dup2 (int old_fd, int new_fd);
\r
39 bool engine_is_ok(const engine_t * engine) {
\r
41 if (engine == NULL) return false;
\r
43 if (!io_is_ok(engine->io)) return false;
\r
50 void engine_open(engine_t * engine) {
\r
52 const char * dir, * command;
\r
53 char string[StringSize];
\r
57 int from_engine[2], to_engine[2];
\r
60 ASSERT(engine!=NULL);
\r
64 dir = option_get_string("EngineDir");
\r
65 my_log("POLYGLOT Dir \"%s\"\n",dir);
\r
67 command = option_get_string("EngineCommand");
\r
68 my_log("POLYGLOT Command \"%s\"\n",command);
\r
70 // parse the command line and create the argument list
\r
72 if (strlen(command) >= StringSize) my_fatal("engine_open(): buffer overflow\n");
\r
73 strcpy(string,command);
\r
77 for (ptr = strtok(string," "); ptr != NULL; ptr = strtok(NULL," ")) {
\r
85 if (pipe(from_engine) == -1) {
\r
86 my_fatal("engine_open(): pipe(): %s\n",strerror(errno));
\r
89 if (pipe(to_engine) == -1) {
\r
90 my_fatal("engine_open(): pipe(): %s\n",strerror(errno));
\r
93 // create the child process
\r
99 my_fatal("engine_open(): fork(): %s\n",strerror(errno));
\r
101 } else if (pid == 0) {
\r
105 // close unused pipe descriptors to avoid deadlocks
\r
107 my_close(from_engine[0]);
\r
108 my_close(to_engine[1]);
\r
110 // attach the pipe to standard input
\r
112 my_dup2(to_engine[0],STDIN_FILENO);
\r
113 my_close(to_engine[0]);
\r
115 // attach the pipe to standard output
\r
117 my_dup2(from_engine[1],STDOUT_FILENO);
\r
118 my_close(from_engine[1]);
\r
120 // attach standard error to standard output
\r
122 my_dup2(STDOUT_FILENO,STDERR_FILENO);
\r
124 // set a low priority
\r
126 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 io_init(engine->io);
\r
169 void engine_close(engine_t * engine) {
\r
171 ASSERT(engine_is_ok(engine));
\r
173 io_close(engine->io);
\r
178 void engine_get(engine_t * engine, char string[], int size) {
\r
180 ASSERT(engine_is_ok(engine));
\r
181 ASSERT(string!=NULL);
\r
184 while (!io_line_ready(engine->io)) {
\r
185 io_get_update(engine->io);
\r
188 if (!io_get_line(engine->io,string,size)) { // EOF
\r
189 my_log("POLYGLOT *** EOF from Engine ***\n");
\r
190 exit(EXIT_SUCCESS);
\r
196 void engine_send(engine_t * engine, const char format[], ...) {
\r
199 char string[StringSize];
\r
201 ASSERT(engine_is_ok(engine));
\r
202 ASSERT(format!=NULL);
\r
206 va_start(arg_list,format);
\r
207 vsprintf(string,format,arg_list);
\r
212 io_send(engine->io,"%s",string);
\r
215 // engine_send_queue()
\r
217 void engine_send_queue(engine_t * engine, const char format[], ...) {
\r
220 char string[StringSize];
\r
222 ASSERT(engine_is_ok(engine));
\r
223 ASSERT(format!=NULL);
\r
227 va_start(arg_list,format);
\r
228 vsprintf(string,format,arg_list);
\r
233 io_send_queue(engine->io,"%s",string);
\r
238 static void my_close(int fd) {
\r
242 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
\r
247 static void my_dup2(int old_fd, int new_fd) {
\r
252 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));
\r
255 // end of posix part
\r
262 #include <stdlib.h>
\r
263 #include <string.h>
\r
264 #include <windows.h>
\r
265 #include <direct.h>
\r
269 #include "engine.h"
\r
270 #include "option.h"
\r
276 static const int StringSize = 4096;
\r
280 static int nQueuePtr = 0;
\r
281 static char szQueueString[StringSize];
\r
282 engine_t Engine[1];
\r
286 DWORD GetWin32Priority(int nice)
\r
289 REALTIME_PRIORITY_CLASS 0x00000100
\r
290 HIGH_PRIORITY_CLASS 0x00000080
\r
291 ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
\r
292 NORMAL_PRIORITY_CLASS 0x00000020
\r
293 BELOW_NORMAL_PRIORITY_CLASS 0x00004000
\r
294 IDLE_PRIORITY_CLASS 0x00000040
\r
296 if (nice < -15) return 0x00000080;
\r
297 if (nice < 0) return 0x00008000;
\r
298 if (nice == 0) return 0x00000020;
\r
299 if (nice < 15) return 0x00004000;
\r
305 void set_affinity(engine_t *engine, int affin){
\r
306 if(affin==-1) return;
\r
307 SetProcessAffinityMask((engine->pipeEngine).hProcess,affin);
\r
312 void engine_send_queue(engine_t * engine,const char *szFormat, ...) {
\r
313 nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
316 void engine_send(engine_t * engine, const char *szFormat, ...) {
\r
317 vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
318 (engine->pipeEngine).LineOutput(szQueueString);
\r
319 my_log("Adapter->Engine: %s\n",szQueueString);
\r
323 void engine_close(engine_t * engine){
\r
324 (engine->pipeEngine).Close();
\r
328 void engine_open(engine_t * engine){
\r
331 if( (my_dir = _getcwd( NULL, 0 )) == NULL )
\r
332 my_fatal("Can't build path: %s\n",strerror(errno));
\r
333 SetCurrentDirectory(option_get_string("EngineDir"));
\r
334 (engine->pipeEngine).Open(option_get_string("EngineCommand"));
\r
335 //play with affinity (bad idea)
\r
336 affinity=option_get_int("Affinity");
\r
337 if(affinity!=-1) set_affinity(engine,affinity); //AAA
\r
339 SetCurrentDirectory(my_dir);
\r
340 // set a low priority
\r
341 if (option_get_bool("UseNice")){
\r
342 my_log("POLYGLOT Adjust Engine Piority\n");
\r
343 SetPriorityClass((engine->pipeEngine).hProcess,
\r
344 GetWin32Priority(option_get_int("NiceValue")));
\r
349 bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){
\r
350 if ((engine->pipeEngine).LineInput(szLineStr)) {
\r
351 my_log("Engine->Adapter: %s\n",szLineStr);
\r
359 void engine_get(engine_t * engine, char *szLineStr, int size){
\r
360 bool data_available;
\r
362 data_available=engine_get_non_blocking(engine,szLineStr,size);
\r
363 if(!data_available){
\r