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
205 void engine_get(engine_t * engine, char string[], int size) {
\r
207 ASSERT(engine_is_ok(engine));
\r
208 ASSERT(string!=NULL);
\r
211 while (!io_line_ready(engine->io)) {
\r
212 io_get_update(engine->io);
\r
215 if (!io_get_line(engine->io,string,size)) { // EOF
\r
216 engine->state|=ENGINE_EOF;
\r
222 void engine_send(engine_t * engine, const char format[], ...) {
\r
225 char string[StringSize];
\r
227 ASSERT(engine_is_ok(engine));
\r
228 ASSERT(format!=NULL);
\r
232 va_start(arg_list,format);
\r
233 vsprintf(string,format,arg_list);
\r
238 io_send(engine->io,"%s",string);
\r
241 // engine_send_queue()
\r
243 void engine_send_queue(engine_t * engine, const char format[], ...) {
\r
246 char string[StringSize];
\r
248 ASSERT(engine_is_ok(engine));
\r
249 ASSERT(format!=NULL);
\r
253 va_start(arg_list,format);
\r
254 vsprintf(string,format,arg_list);
\r
259 io_send_queue(engine->io,"%s",string);
\r
264 static void my_close(int fd) {
\r
268 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
\r
273 static void my_dup2(int old_fd, int new_fd) {
\r
278 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));
\r
281 // end of posix part
\r
288 #include <stdlib.h>
\r
289 #include <string.h>
\r
290 #include <windows.h>
\r
291 #include <direct.h>
\r
295 #include "engine.h"
\r
296 #include "option.h"
\r
302 static const int StringSize = 4096;
\r
306 static int nQueuePtr = 0;
\r
307 static char szQueueString[StringSize];
\r
308 engine_t Engine[1];
\r
312 DWORD GetWin32Priority(int nice)
\r
315 REALTIME_PRIORITY_CLASS 0x00000100
\r
316 HIGH_PRIORITY_CLASS 0x00000080
\r
317 ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
\r
318 NORMAL_PRIORITY_CLASS 0x00000020
\r
319 BELOW_NORMAL_PRIORITY_CLASS 0x00004000
\r
320 IDLE_PRIORITY_CLASS 0x00000040
\r
322 if (nice < -15) return 0x00000080;
\r
323 if (nice < 0) return 0x00008000;
\r
324 if (nice == 0) return 0x00000020;
\r
325 if (nice < 15) return 0x00004000;
\r
331 void set_affinity(engine_t *engine, int affin){
\r
332 if(affin==-1) return;
\r
333 SetProcessAffinityMask((engine->pipeEngine).hProcess,affin);
\r
338 void engine_set_nice_value(engine_t *engine, int value){
\r
339 SetPriorityClass((engine->pipeEngine).hProcess,
\r
340 GetWin32Priority(value));
\r
344 void engine_send_queue(engine_t * engine,const char *szFormat, ...) {
\r
345 nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
348 void engine_send(engine_t * engine, const char *szFormat, ...) {
\r
349 vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
350 (engine->pipeEngine).LineOutput(szQueueString);
\r
351 my_log("Adapter->Engine: %s\n",szQueueString);
\r
355 void engine_close(engine_t * engine){
\r
356 char string[StringSize];
\r
357 (engine->pipeEngine).Close();
\r
359 while (!engine_eof(Engine)) {
\r
360 engine_get(Engine,string,StringSize);
\r
362 (engine->pipeEngine).Kill();
\r
366 void engine_open(engine_t * engine){
\r
370 if( (my_dir = _getcwd( NULL, 0 )) == NULL )
\r
371 my_fatal("Can't build path: %s\n",strerror(errno));
\r
372 SetCurrentDirectory(option_get_string("EngineDir"));
\r
373 (engine->pipeEngine).Open(option_get_string("EngineCommand"));
\r
374 if((engine->pipeEngine).Active()){
\r
375 engine->state|=ENGINE_ACTIVE;
\r
376 //play with affinity (bad idea)
\r
377 affinity=option_get_int("Affinity");
\r
378 if(affinity!=-1) set_affinity(engine,affinity); //AAA
\r
380 SetCurrentDirectory(my_dir);
\r
381 // set a low priority
\r
382 if (option_get_bool("UseNice")){
\r
383 my_log("POLYGLOT Adjust Engine Piority\n");
\r
384 engine_set_nice_value(engine, option_get_int("NiceValue"));
\r
390 bool engine_active(engine_t *engine){
\r
391 return (engine->state & ENGINE_ACTIVE)!=0;
\r
394 bool engine_eof(engine_t *engine){
\r
395 return (engine->state & ENGINE_EOF)!=0;
\r
398 bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){
\r
399 if(engine_eof(engine)){ return false;}
\r
400 if ((engine->pipeEngine).LineInput(szLineStr)) {
\r
401 my_log("Engine->Adapter: %s\n",szLineStr);
\r
405 if(engine->pipeEngine.EOF_()){
\r
406 my_log("POLYGLOT EOF received from engine\n");
\r
407 engine->state|=ENGINE_EOF;
\r
413 void engine_get(engine_t * engine, char *szLineStr, int size){
\r
414 bool data_available;
\r
415 if(engine_eof(engine))return;
\r
417 data_available=engine_get_non_blocking(engine,szLineStr,size);
\r
418 if(!data_available && !engine_eof(engine)){
\r