viewer/grphshm.cpp

Go to the documentation of this file.
00001 
00020 #include          "mfcpch.h"
00021 #include          "evntlst.h"
00022 #ifdef __UNIX__
00023 #include          <sys/ipc.h>
00024 #include          <sys/shm.h>
00025 //#include                                      <osfcn.h>
00026 #include          <errno.h>
00027 //#include                                      "pipes.h"
00028 #include          "fileerr.h"
00029 //#include                                      "grpherr.h"
00030 //#include                                      "basefile.h"
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;          /*shared memory */
00046 EXTERN WINFD sbfds[MAXWINDOWS];  /*file descriptors */
00047 EXTERN INT16 maxsbfd = 0;        /*no of fds in use */
00048 #ifdef __MSW32__
00049                                  //event thread id
00050 EXTERN DWORD event_id = (DWORD) - 1;
00051 #endif
00052 
00061 void start_sbdaemon() {  /*start the daemon */
00062   #if defined (__UNIX__) || defined(__MSW32__)
00063   char *shmaddr;                 /*address to attach */
00064   char *sbenv;                   /*SB_DISPLAY_ADDR */
00065   INT32 sbaddr;                  /*starbase address */
00066   INT32 wmshm;                   //windows shared mem
00067   char arg1[MAX_PATH];           /*shmid argument */
00068   char arg2[MAX_PATH];           /*shmstart argument */
00069   char arg3[MAX_PATH];           /*shmsize argument */
00070   const char *argv[5];           /*args of sbdaemon */
00071                                  /*for pipe usage */
00072   static char pipebuffer[PIPESIZE];
00073 
00074   sbenv = getenv (SBADDR);       /*get SB_DISPLAY_ADDR */
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                                  /*default address */
00081   shmaddr = (char *) sbaddr - (wmshm + SHMSIZE + SHMOFFSET);
00082 
00083   if (!remote_display (arg1)) {
00084     shminfo.shmsize = SHMSIZE;   /*size of segment */
00085     #ifdef __UNIX__
00086     shminfo.shmid = shmget (IPC_PRIVATE, SHMSIZE, USER_RW);
00087     /*get shm segment */
00088     //    if (shminfo.shmid==-1)
00089     //    NO_SHM_SEGMENT.error("start_sbdaemon",ABORT,"Errno=%d",errno);
00090     #ifdef hp9000s800
00091                                  /*attach it */
00092     shminfo.shmstart = shmat (shminfo.shmid, 0, 0);
00093     if ((int) shminfo.shmstart == -1)
00094     #else //hp9000s800
00095                                  /*attach it */
00096       shminfo.shmstart = shmat (shminfo.shmid, shmaddr, 0);
00097     //    if (shminfo.shmstart!=shmaddr)
00098     #endif //hp9000s800
00099     //            SHM_ATTACH_FAILED.error("start_sbdaemon",ABORT,"Errno=%d",errno);
00100     #else //__UNIX__
00101     SECURITY_ATTRIBUTES security;//for handles
00102 
00103     security.nLength = sizeof (security);
00104     security.lpSecurityDescriptor = NULL;
00105                                  //make it inheritable
00106     security.bInheritHandle = TRUE;
00107                                  //anonymous
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;                    //quietly fail
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                                  /*set up args */
00123     sprintf (arg1, "%d", shminfo.shmid);
00124     sprintf (arg2, "%p", shminfo.shmstart);
00125     sprintf (arg3, INT32FORMAT, shminfo.shmsize);
00126     argv[0] = SBDAEMON;          /*set up argv */
00127     argv[1] = arg1;
00128     argv[2] = arg2;
00129     argv[3] = arg3;
00130     argv[4] = NULL;
00131   }
00132   else {
00133     shmaddr = NULL;              //remote
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                                  /*not using shm */
00142     shminfo.shmstart = pipebuffer;
00143     shminfo.shmsize = PIPESIZE;  /*size of pipe buffer */
00144     #ifdef __UNIX__
00145                                  /*command on host */
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                                  /*command on host */
00150     sprintf (arg2, "%s -1 0 %d %s", SBDAEMON, shminfo.shmsize, getenv (DISP));
00151     #endif //__UNIX__
00152     argv[0] = REMSH;             /*set up argv */
00153     argv[1] = arg1;              /*host to use */
00154     argv[2] = arg2;
00155     argv[3] = NULL;
00156   }
00157 
00158   shminfo.usedsize = 0;          /*none used yet */
00159 
00160   #ifdef __UNIX__
00161   //   shminfo.pid=two_way_pipe(argv[0],argv,shminfo.fds);       /*start daemon*/
00162   #else //__UNIX__
00163   if (two_way_pipe (argv[0], argv, shminfo.fds) != 0) {
00164     cleanup_sbdaemon(); 
00165   }
00166   else {
00167                                  //anonymous
00168     event_sem = CreateSemaphore (NULL, 1, 1, NULL);
00169     //xiaofan
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() {  /*forget about the daemon */
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(            //check for remote
00226                      char *name  //name of host
00227                     ) {
00228   #if defined (__UNIX__) || defined(__MSW32__)
00229   char *xenv;                    /*DISPLAY environ */
00230   char *nameend;                 //end of name
00231   #ifdef __UNIX__
00232   char thishost[MAX_PATH];       //current host
00233   #endif
00234 
00235   xenv = getenv (DISP);          /*get display variable */
00236   if (xenv != NULL) {
00237     strcpy(name, xenv);
00238     nameend = strchr (name, ':');
00239     if (nameend != NULL)
00240       *nameend = '\0';           /*chop display off */
00241     nameend = strchr (name, '.');
00242     if (nameend != NULL)
00243       *nameend = '\0';           /*chop resolv off */
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';         /*chop resolv off */
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(            /*get memory */
00271                     INT32 size  /*required size */
00272                    ) {
00273   void *segment;                 /*return segment */
00274 
00275   if (shminfo.shmstart == NULL)
00276     return NULL;                 //no daemon connection
00277   size = (size + 3) & ~3;
00278   if (size > shminfo.shmsize)
00279     return NULL;
00280                                  /*too full? */
00281   if (shminfo.usedsize + size > shminfo.shmsize
00282   || shminfo.usedsize < 0) {     /*or read pending */
00283     kick_daemon(AWAIT_BUFFER);  /*get it to read */
00284   }
00285                                  /*address of segment */
00286   segment = (char *) shminfo.shmstart + shminfo.usedsize;
00287   shminfo.usedsize += size;      /*sum used sizes */
00288   return segment;
00289 }
00290 
00291 
00301 void kick_daemon(           /*empty queue */
00302                  INT8 mode  /*control mode */
00303                 ) {
00304   #ifndef __MAC__
00305   SBD_GRAPHICS_EVENT event;      /*event from daemon */
00306   GRAPHICS_EVENT real_event;     //converted format
00307   #ifdef __MSW32__
00308   unsigned long nwrite;
00309   unsigned long nread;           //bytes read
00310   char pipe_char[2];             //char from pipe
00311   INT32 pipe_index;              //index to event queue
00312   #endif  //__MSW32__
00313   static INT16 reads_pending = 0;/*acknowledges pending */
00314 
00315   if (mode == COUNT_READS) {
00316     lock_events();
00317     reads_pending--;             /*got a read */
00318     unlock_events();
00319     return;
00320   }
00321   if (shminfo.shmstart == NULL)
00322     return;                      //no connection
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;    /*can use it now */
00352       }
00353       else
00354         shminfo.usedsize = -1;   /*need to wait */
00355       lock_events();
00356       reads_pending++;           /*acknowledges due */
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 //__UNIX__
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                                  /*add event to queue */
00393                 add_event(&real_event);
00394             }
00395             else
00396               reads_pending--;   /*got acknowledge */
00397               #ifdef __MSW32__
00398           }
00399         }
00400         else
00401           Sleep (50);   // a minute? this isn't 1989 :)
00402       #endif //__MSW32__
00403       }
00404       if (shminfo.usedsize < 0)  //must be reentrant
00405           shminfo.usedsize = 0;  /*none used now */
00406     }
00407    #endif // ! __MAC__
00408   }
00409 
00410   #ifdef __MSW32__
00411   /**********************************************************************
00412    * two_way_pipe
00413    *
00414    * Open the process and connect a 2 way pipe to its stdin and stdout.
00415    **********************************************************************/
00416 
00417   int
00418     two_way_pipe (               //do one file
00419     const char *file,            //program to run
00420     const char *argv[],          //args to execvp
00421     HANDLE fds[]                 //output fds
00422   ) {
00423     int argind;                  //argument index
00424       HANDLE infds[2];           //input fds
00425       HANDLE outfds[2];          //output fds
00426       HANDLE sends[2];           //fds for child
00427       HANDLE process;            //current process
00428       STARTUPINFO start_info;    //start information
00429                                  //process info
00430       PROCESS_INFORMATION proc_info;
00431       char cmd[MAX_PATH * 2];    //final command line
00432 
00433       if (CreatePipe (&infds[0], &infds[1], NULL, PIPESIZE) == 0
00434         || CreatePipe (&outfds[0], &outfds[1], NULL, PIPESIZE) == 0)
00435         return -1;
00436     /*   if (_pipe(infds,PIPESIZE,_O_BINARY)<0
00437       || _pipe(outfds,PIPESIZE,_O_BINARY)<0)
00438         return -1;   */
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__

Generated on Wed Feb 28 19:49:12 2007 for Tesseract by  doxygen 1.5.1