00001
00020 #include "mfcpch.h"
00021 #include "evntlst.h"
00022 #ifdef __UNIX__
00023 #include <sys/ipc.h>
00024 #include <sys/shm.h>
00025
00026 #include <errno.h>
00027
00028 #include "fileerr.h"
00029
00030
00031 #include <unistd.h>
00032 #elif defined(__MSW32__)
00033 #include <io.h>
00034 #include <fcntl.h>
00035 #include <process.h>
00036 #include <stdio.h>
00037 #else
00038 #endif
00039 #include <string.h>
00040 #include "grphics.h"
00041 #include "grphshm.h"
00042
00043 #define EXTERN
00044
00045 EXTERN SHMINFO shminfo;
00046 EXTERN WINFD sbfds[MAXWINDOWS];
00047 EXTERN INT16 maxsbfd = 0;
00048 #ifdef __MSW32__
00049
00050 EXTERN DWORD event_id = (DWORD) - 1;
00051 #endif
00052
00061 void start_sbdaemon() {
00062 #if defined (__UNIX__) || defined(__MSW32__)
00063 char *shmaddr;
00064 char *sbenv;
00065 INT32 sbaddr;
00066 INT32 wmshm;
00067 char arg1[MAX_PATH];
00068 char arg2[MAX_PATH];
00069 char arg3[MAX_PATH];
00070 const char *argv[5];
00071
00072 static char pipebuffer[PIPESIZE];
00073
00074 sbenv = getenv (SBADDR);
00075 if (sbenv == NULL || sscanf (sbenv, INT32FORMAT, &sbaddr) != 1)
00076 sbaddr = SBDEFAULT;
00077 shmaddr = getenv (WMSHM);
00078 if (shmaddr == NULL || sscanf (shmaddr, INT32FORMAT, &wmshm) != 1)
00079 wmshm = WMSHMDEFAULT;
00080
00081 shmaddr = (char *) sbaddr - (wmshm + SHMSIZE + SHMOFFSET);
00082
00083 if (!remote_display (arg1)) {
00084 shminfo.shmsize = SHMSIZE;
00085 #ifdef __UNIX__
00086 shminfo.shmid = shmget (IPC_PRIVATE, SHMSIZE, USER_RW);
00087
00088
00089
00090 #ifdef hp9000s800
00091
00092 shminfo.shmstart = shmat (shminfo.shmid, 0, 0);
00093 if ((int) shminfo.shmstart == -1)
00094 #else //hp9000s800
00095
00096 shminfo.shmstart = shmat (shminfo.shmid, shmaddr, 0);
00097
00098 #endif //hp9000s800
00099
00100 #else //__UNIX__
00101 SECURITY_ATTRIBUTES security;
00102
00103 security.nLength = sizeof (security);
00104 security.lpSecurityDescriptor = NULL;
00105
00106 security.bInheritHandle = TRUE;
00107
00108 shminfo.shmid = CreateFileMapping ((HANDLE) 0xffffffff, &security,
00109 PAGE_READWRITE, 0, shminfo.shmsize + 3 * sizeof (INT32)
00110 + EVENTSIZE * sizeof (SBD_GRAPHICS_EVENT), NULL);
00111 if (shminfo.shmid == NULL) {
00112 shminfo.shmstart = NULL;
00113 return;
00114 }
00115 shminfo.shmstart =
00116 MapViewOfFile (shminfo.shmid, FILE_MAP_WRITE, 0, 0, 0);
00117 if (shminfo.shmstart == NULL)
00118 return;
00119 EVENT_TAIL = 0;
00120 EVENT_HEAD = 0;
00121 #endif //__UNIX__
00122
00123 sprintf (arg1, "%d", shminfo.shmid);
00124 sprintf (arg2, "%p", shminfo.shmstart);
00125 sprintf (arg3, INT32FORMAT, shminfo.shmsize);
00126 argv[0] = SBDAEMON;
00127 argv[1] = arg1;
00128 argv[2] = arg2;
00129 argv[3] = arg3;
00130 argv[4] = NULL;
00131 }
00132 else {
00133 shmaddr = NULL;
00134 fprintf (stderr, "start_sbdaemon:using %s to connect to machine %s\n",
00135 REMSH, arg1);
00136 #ifdef __UNIX__
00137 shminfo.shmid = -1;
00138 #else //__UNIX__
00139 shminfo.shmid = NULL;
00140 #endif //__UNIX__
00141
00142 shminfo.shmstart = pipebuffer;
00143 shminfo.shmsize = PIPESIZE;
00144 #ifdef __UNIX__
00145
00146 sprintf (arg2, "%s=0x%x; export %s; %s -1 0 " INT32FORMAT " %s",
00147 SBADDR, sbaddr, SBADDR, SBDAEMON, shminfo.shmsize, getenv (DISP));
00148 #else//__UNIX__
00149
00150 sprintf (arg2, "%s -1 0 %d %s", SBDAEMON, shminfo.shmsize, getenv (DISP));
00151 #endif //__UNIX__
00152 argv[0] = REMSH;
00153 argv[1] = arg1;
00154 argv[2] = arg2;
00155 argv[3] = NULL;
00156 }
00157
00158 shminfo.usedsize = 0;
00159
00160 #ifdef __UNIX__
00161
00162 #else //__UNIX__
00163 if (two_way_pipe (argv[0], argv, shminfo.fds) != 0) {
00164 cleanup_sbdaemon();
00165 }
00166 else {
00167
00168 event_sem = CreateSemaphore (NULL, 1, 1, NULL);
00169
00170 _beginthread (event_reader, 0, &shminfo.fds[INFD]);
00171 }
00172 #endif //__UNIX__
00173 #endif //defined (__UNIX__) || defined(__MSW32__)
00174 }
00175
00176
00182 void cleanup_sbdaemon() {
00183 #ifdef __MSW32__
00184 if (shminfo.fds[INFD] != NULL) {
00185 CloseHandle (shminfo.fds[INFD]);
00186 shminfo.fds[INFD] = 0;
00187 }
00188 if (shminfo.fds[OUTFD] != NULL) {
00189 CloseHandle (shminfo.fds[OUTFD]);
00190 shminfo.fds[OUTFD] = 0;
00191 }
00192 if (shminfo.shmstart != NULL) {
00193 UnmapViewOfFile (shminfo.shmstart);
00194 shminfo.shmstart = NULL;
00195 }
00196 if (shminfo.shmid != NULL) {
00197 CloseHandle (shminfo.shmid);
00198 shminfo.shmid = NULL;
00199 }
00200 if (event_sem != NULL) {
00201 CloseHandle(event_sem);
00202 event_sem = NULL;
00203 }
00204 #elif defined(__UNIX__)
00205 if (shminfo.fds[INFD] > 0) {
00206 close (shminfo.fds[INFD]);
00207 shminfo.fds[INFD] = 0;
00208 }
00209 if (shminfo.fds[OUTFD] > 0) {
00210 close (shminfo.fds[OUTFD]);
00211 shminfo.fds[OUTFD] = 0;
00212 }
00213 shminfo.shmstart = NULL;
00214 #endif //defined(__UNIX__)
00215 }
00216
00217
00225 BOOL8 remote_display(
00226 char *name
00227 ) {
00228 #if defined (__UNIX__) || defined(__MSW32__)
00229 char *xenv;
00230 char *nameend;
00231 #ifdef __UNIX__
00232 char thishost[MAX_PATH];
00233 #endif
00234
00235 xenv = getenv (DISP);
00236 if (xenv != NULL) {
00237 strcpy(name, xenv);
00238 nameend = strchr (name, ':');
00239 if (nameend != NULL)
00240 *nameend = '\0';
00241 nameend = strchr (name, '.');
00242 if (nameend != NULL)
00243 *nameend = '\0';
00244 #ifdef __UNIX__
00245 if (strcmp (name, LOCAL1) && strcmp (name, LOCAL2)
00246 && gethostname (thishost, MAX_PATH) >= 0) {
00247 nameend = strchr (thishost, '.');
00248 if (nameend != NULL)
00249 *nameend = '\0';
00250 if (strcmp (name, thishost)) {
00251 return TRUE;
00252 }
00253 }
00254 #else
00255 return TRUE;
00256 #endif
00257 }
00258 #endif
00259 return FALSE;
00260 }
00261
00262
00270 DLLSYM void *getshm(
00271 INT32 size
00272 ) {
00273 void *segment;
00274
00275 if (shminfo.shmstart == NULL)
00276 return NULL;
00277 size = (size + 3) & ~3;
00278 if (size > shminfo.shmsize)
00279 return NULL;
00280
00281 if (shminfo.usedsize + size > shminfo.shmsize
00282 || shminfo.usedsize < 0) {
00283 kick_daemon(AWAIT_BUFFER);
00284 }
00285
00286 segment = (char *) shminfo.shmstart + shminfo.usedsize;
00287 shminfo.usedsize += size;
00288 return segment;
00289 }
00290
00291
00301 void kick_daemon(
00302 INT8 mode
00303 ) {
00304 #ifndef __MAC__
00305 SBD_GRAPHICS_EVENT event;
00306 GRAPHICS_EVENT real_event;
00307 #ifdef __MSW32__
00308 unsigned long nwrite;
00309 unsigned long nread;
00310 char pipe_char[2];
00311 INT32 pipe_index;
00312 #endif //__MSW32__
00313 static INT16 reads_pending = 0;
00314
00315 if (mode == COUNT_READS) {
00316 lock_events();
00317 reads_pending--;
00318 unlock_events();
00319 return;
00320 }
00321 if (shminfo.shmstart == NULL)
00322 return;
00323 if (shminfo.usedsize > 0) {
00324 #ifdef __UNIX__
00325 if (write
00326 (shminfo.fds[OUTFD], (const char *) &shminfo.usedsize,
00327 sizeof (INT32)) != sizeof (INT32))
00328 WRITEFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
00329 #else
00330 PRIMITIVES = shminfo.usedsize;
00331 if (WriteFile (shminfo.fds[OUTFD], "xx", 2, &nwrite, NULL) == 0
00332 || nwrite != 2) {
00333 cleanup_sbdaemon();
00334 return;
00335 }
00336 #endif
00337 #ifdef __UNIX__
00338 if (shminfo.shmid < 0) {
00339 if (write (shminfo.fds[OUTFD], (const char *) shminfo.shmstart,
00340 shminfo.usedsize) != shminfo.usedsize)
00341 WRITEFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
00342 #else //__UNIX__
00343 if (shminfo.shmid == NULL) {
00344 if (WriteFile (shminfo.fds[OUTFD], (const char *) shminfo.shmstart,
00345 shminfo.usedsize, &nwrite, NULL) == 0
00346 || nwrite != (UINT32) shminfo.usedsize) {
00347 cleanup_sbdaemon();
00348 return;
00349 }
00350 #endif //__UNIX__
00351 shminfo.usedsize = 0;
00352 }
00353 else
00354 shminfo.usedsize = -1;
00355 lock_events();
00356 reads_pending++;
00357 unlock_events();
00358 }
00359 if (mode == FLUSH_IN || reads_pending > MAX_PENDING || mode == AWAIT_BUFFER
00360 #ifdef __UNIX__
00361 && shminfo.shmid < 0)
00362 #else //__UNIX__
00363 && shminfo.shmid != NULL)
00364 #endif
00365 {
00366 while (reads_pending > 0) {
00367 #ifdef __MSW32__
00368 if (event_id == GetCurrentThreadId ()) {
00369 if (ReadFile (shminfo.fds[INFD], pipe_char, 2, &nread, NULL) != 0
00370 && nread == 2) {
00371 pipe_index = EVENT_HEAD;
00372 event = EVENT_INDEX (pipe_index);
00373 pipe_index++;
00374 if (pipe_index >= EVENTSIZE)
00375 pipe_index = 0;
00376 EVENT_HEAD = pipe_index;
00377 #endif //__MSW32__
00378 #ifdef __UNIX__
00379 if (read
00380 (shminfo.fds[INFD], &event,
00381 sizeof (SBD_GRAPHICS_EVENT)) !=
00382 sizeof (SBD_GRAPHICS_EVENT))
00383 READFAILED.error ("kick_daemon", EXIT, "sbdaemon pipe");
00384 #endif //__UNIX__
00385 if (event.type != QUEUE_CLEAR) {
00386 real_event.fildes = event.fd;
00387 real_event.type = event.type;
00388 real_event.key = event.key;
00389 real_event.x = event.x;
00390 real_event.y = event.y;
00391 real_event.next = NULL;
00392
00393 add_event(&real_event);
00394 }
00395 else
00396 reads_pending--;
00397 #ifdef __MSW32__
00398 }
00399 }
00400 else
00401 Sleep (50);
00402 #endif //__MSW32__
00403 }
00404 if (shminfo.usedsize < 0)
00405 shminfo.usedsize = 0;
00406 }
00407 #endif // ! __MAC__
00408 }
00409
00410 #ifdef __MSW32__
00411
00412
00413
00414
00415
00416
00417 int
00418 two_way_pipe (
00419 const char *file,
00420 const char *argv[],
00421 HANDLE fds[]
00422 ) {
00423 int argind;
00424 HANDLE infds[2];
00425 HANDLE outfds[2];
00426 HANDLE sends[2];
00427 HANDLE process;
00428 STARTUPINFO start_info;
00429
00430 PROCESS_INFORMATION proc_info;
00431 char cmd[MAX_PATH * 2];
00432
00433 if (CreatePipe (&infds[0], &infds[1], NULL, PIPESIZE) == 0
00434 || CreatePipe (&outfds[0], &outfds[1], NULL, PIPESIZE) == 0)
00435 return -1;
00436
00437
00438
00439 process = GetCurrentProcess ();
00440 if (DuplicateHandle (process, outfds[0],
00441 process, &sends[0], GENERIC_READ, TRUE,
00442 DUPLICATE_CLOSE_SOURCE) == 0)
00443 return -1;
00444 if (DuplicateHandle (process, infds[1],
00445 process, &sends[1], GENERIC_WRITE, TRUE,
00446 DUPLICATE_CLOSE_SOURCE) == 0)
00447 return -1;
00448
00449 cmd[0] = '\0';
00450 for (argind = 0; argv[argind] != NULL; argind++) {
00451 if (argind != 0)
00452 strcat (cmd, " ");
00453 strcat (cmd, argv[argind]);
00454 }
00455
00456 GetStartupInfo(&start_info);
00457 start_info.wShowWindow = FALSE;
00458 start_info.hStdInput = sends[0];
00459 start_info.hStdOutput = sends[1];
00460 start_info.dwFlags = STARTF_USESTDHANDLES;
00461 if (!CreateProcess (NULL, (char *) cmd, NULL, NULL, TRUE,
00462 CREATE_NO_WINDOW | CREATE_SUSPENDED, NULL, NULL,
00463 &start_info, &proc_info))
00464 return -1;
00465 CloseHandle (sends[0]);
00466 CloseHandle (sends[1]);
00467 CloseHandle (proc_info.hProcess);
00468 ResumeThread (proc_info.hThread);
00469 CloseHandle (proc_info.hThread);
00470 fds[INFD] = infds[0];
00471 fds[OUTFD] = outfds[1];
00472 return 0;
00473 }
00474 #endif //__MSW32__