13 #include <sys/types.h>
\r
14 #include <sys/resource.h>
\r
25 static const 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
164 io_init(engine->io);
\r
168 // engine_set_nice_value()
\r
170 void engine_set_nice_value(engine_t * engine, int value){
\r
171 setpriority(PRIO_PROCESS,engine->pid,value);
\r
177 void engine_close(engine_t * engine) {
\r
179 ASSERT(engine_is_ok(engine));
\r
181 io_close(engine->io);
\r
186 void engine_get(engine_t * engine, char string[], int size) {
\r
188 ASSERT(engine_is_ok(engine));
\r
189 ASSERT(string!=NULL);
\r
192 while (!io_line_ready(engine->io)) {
\r
193 io_get_update(engine->io);
\r
196 if (!io_get_line(engine->io,string,size)) { // EOF
\r
197 my_log("POLYGLOT *** EOF from Engine ***\n");
\r
198 exit(EXIT_SUCCESS);
\r
204 void engine_send(engine_t * engine, const char format[], ...) {
\r
207 char string[StringSize];
\r
209 ASSERT(engine_is_ok(engine));
\r
210 ASSERT(format!=NULL);
\r
214 va_start(arg_list,format);
\r
215 vsprintf(string,format,arg_list);
\r
220 io_send(engine->io,"%s",string);
\r
223 // engine_send_queue()
\r
225 void engine_send_queue(engine_t * engine, const char format[], ...) {
\r
228 char string[StringSize];
\r
230 ASSERT(engine_is_ok(engine));
\r
231 ASSERT(format!=NULL);
\r
235 va_start(arg_list,format);
\r
236 vsprintf(string,format,arg_list);
\r
241 io_send_queue(engine->io,"%s",string);
\r
246 static void my_close(int fd) {
\r
250 if (close(fd) == -1) my_fatal("my_close(): close(): %s\n",strerror(errno));
\r
255 static void my_dup2(int old_fd, int new_fd) {
\r
260 if (dup2(old_fd,new_fd) == -1) my_fatal("my_dup2(): dup2(): %s\n",strerror(errno));
\r
263 // end of posix part
\r
270 #include <stdlib.h>
\r
271 #include <string.h>
\r
272 #include <windows.h>
\r
273 #include <direct.h>
\r
277 #include "engine.h"
\r
278 #include "option.h"
\r
284 static const int StringSize = 4096;
\r
288 static int nQueuePtr = 0;
\r
289 static char szQueueString[StringSize];
\r
290 engine_t Engine[1];
\r
294 DWORD GetWin32Priority(int nice)
\r
297 REALTIME_PRIORITY_CLASS 0x00000100
\r
298 HIGH_PRIORITY_CLASS 0x00000080
\r
299 ABOVE_NORMAL_PRIORITY_CLASS 0x00008000
\r
300 NORMAL_PRIORITY_CLASS 0x00000020
\r
301 BELOW_NORMAL_PRIORITY_CLASS 0x00004000
\r
302 IDLE_PRIORITY_CLASS 0x00000040
\r
304 if (nice < -15) return 0x00000080;
\r
305 if (nice < 0) return 0x00008000;
\r
306 if (nice == 0) return 0x00000020;
\r
307 if (nice < 15) return 0x00004000;
\r
313 void set_affinity(engine_t *engine, int affin){
\r
314 if(affin==-1) return;
\r
315 SetProcessAffinityMask((engine->pipeEngine).hProcess,affin);
\r
320 void engine_set_nice_value(engine_t *engine, int value){
\r
321 SetPriorityClass((engine->pipeEngine).hProcess,
\r
322 GetWin32Priority(value));
\r
326 void engine_send_queue(engine_t * engine,const char *szFormat, ...) {
\r
327 nQueuePtr += vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
330 void engine_send(engine_t * engine, const char *szFormat, ...) {
\r
331 vsprintf(szQueueString + nQueuePtr, szFormat, (va_list) (&szFormat + 1));
\r
332 (engine->pipeEngine).LineOutput(szQueueString);
\r
333 my_log("Adapter->Engine: %s\n",szQueueString);
\r
337 void engine_close(engine_t * engine){
\r
338 (engine->pipeEngine).Close();
\r
342 void engine_open(engine_t * engine){
\r
345 if( (my_dir = _getcwd( NULL, 0 )) == NULL )
\r
346 my_fatal("Can't build path: %s\n",strerror(errno));
\r
347 SetCurrentDirectory(option_get_string("EngineDir"));
\r
348 (engine->pipeEngine).Open(option_get_string("EngineCommand"));
\r
349 //play with affinity (bad idea)
\r
350 affinity=option_get_int("Affinity");
\r
351 if(affinity!=-1) set_affinity(engine,affinity); //AAA
\r
353 SetCurrentDirectory(my_dir);
\r
354 // set a low priority
\r
355 if (option_get_bool("UseNice")){
\r
356 my_log("POLYGLOT Adjust Engine Piority\n");
\r
357 engine_set_nice_value(engine, option_get_int("NiceValue"));
\r
362 bool engine_get_non_blocking(engine_t * engine, char *szLineStr, int size){
\r
363 if ((engine->pipeEngine).LineInput(szLineStr)) {
\r
364 my_log("Engine->Adapter: %s\n",szLineStr);
\r
372 void engine_get(engine_t * engine, char *szLineStr, int size){
\r
373 bool data_available;
\r
375 data_available=engine_get_non_blocking(engine,szLineStr,size);
\r
376 if(!data_available){
\r