sic_comm.c

Go to the documentation of this file.
00001 
00017 /***************************************************************************** 
00018  *                              Dependencies                                 * 
00019  *****************************************************************************/
00020 
00021 #include "sic_comm.h"
00022 
00023 #ifndef WIN32
00024 #include <stdio.h>
00025 #include <stdlib.h>
00026 #include <errno.h>
00027 #include <time.h>
00028 #include <string.h>
00029 #include <unistd.h>
00030 #include <sys/wait.h>
00031 #include <sys/stat.h>
00032 #endif
00033 
00034 #ifdef GAG_SYSV
00035 #include <sys/shm.h>
00036 #include <sys/sem.h>
00037 #elif defined(WIN32)
00038 #else /* GAG_SYSV */
00039 #include <fcntl.h>
00040 #include <sys/mman.h>
00041 #include <semaphore.h>
00042 #endif /* GAG_SYSV */
00043 #ifdef cygwin
00044 #include <limits.h>
00045 #endif /* cygwin */
00046 
00047 #include "ctrlc.h"
00048 #include "sic_error.h"
00049 #include "gag_trace.h"
00050 
00051 /***************************************************************************** 
00052  *                          Macros & Definitions                             * 
00053  *****************************************************************************/
00054 
00055 #define SIC_DEBUG_COMM
00056 #if defined(darwin) || defined(cygwin) || defined(linux)
00057 #define SIC_USE_SEM_OPEN
00058 #endif
00059 
00060 #ifndef SIGCLD
00061 #define SIGCLD SIGCHLD
00062 #endif /* SIGCLD */
00063 
00064 #ifdef SIC_DEBUG_COMM
00065 #define SIC_ASSERT( message, condition) \
00066     { if (!(condition)) fprintf( stderr, "SIC_ASSERT: %s\n", message); }
00067 #else /* SIC_DEBUG_COMM */
00068 #define SIC_ASSERT( message, condition)
00069 #endif /* SIC_DEBUG_COMM */
00070 
00071 #define MAX_ARGC 32
00072 #define MAX_ARGV 256
00073 
00074 #define SIC_MAX_WIDGET_ON_BOARD 1000
00075 #define SIC_MAX_SHM_NAME 32
00076 #define SIC_MAX_SEM_NAME_FOR_PORTABILITY 14
00077 #define SIC_MAX_HANDLERS 32
00078 
00079 /* Event Ids */
00080 #define SIC_MODIFIED_VARIABLE_EVENT 1
00081 #define SIC_REDRAW_PROMPT_EVENT 2
00082 
00083 #if defined(GAG_SYSV)
00084 typedef struct {
00085     int sem_id;
00086 } sic_sem_t;
00087 #define SIC_SEM_ID(x) ((x)->sem_id)
00088 #elif defined(WIN32)
00089 typedef struct {
00090     HANDLE sem_id;
00091 } sic_sem_t;
00092 #define SIC_SEM_ID(x) ((x)->sem_id)
00093 #else /* defined(GAG_SYSV) */
00094 typedef struct {
00095 #ifdef SIC_USE_SEM_OPEN
00096     sem_t *sem_id;
00097 #define SIC_SEM_ID(x) ((x)->sem_id)
00098 #else /* SIC_USE_SEM_OPEN */
00099     sem_t sem_id;
00100 #define SIC_SEM_ID(x) (&(x)->sem_id)
00101 #endif /* SIC_USE_SEM_OPEN */
00102     char name[SIC_MAX_SEM_NAME_FOR_PORTABILITY];
00103 } sic_sem_t;
00104 
00105 #endif /* defined(GAG_SYSV) */
00106 
00107 typedef struct {
00108     task_t task;
00109     int event_id;
00110     void (*listener)();
00111     int sig_num;
00112 } sic_listener_handler_t;
00113 
00114 typedef struct {
00115     task_t master_task;
00116     task_t keyboard_task;
00117     int trace_fd;
00118     sic_sem_t comm_board_access;
00119     sic_sem_t draw_prompt;
00120     sic_sem_t write_command;
00121     sic_sem_t read_command;
00122     sic_sem_t listener_acquit;
00123     sic_sem_t widget_board_access;
00124     sic_sem_t widget_created;
00125     int widget_board_id;
00126     command_line_t command_line;
00127     char pushed_command_text[MAXBUF];
00128     sic_command_from_t from;
00129     int listener_count;
00130     sic_listener_handler_t listeners[SIC_MAX_HANDLERS];
00131     int event_id;
00132 } sic_comm_board_t;
00133 
00134 typedef struct {
00135     char window_title[TITLELENGTH];
00136     char help_filename[HLPFILELNGTH];
00137     char returned_command[COMMANDLENGTH];
00138     int returned_code;
00139     sic_widget_def_t modified_widget;
00140     int widget_count;
00141     sic_widget_def_t widgets[SIC_MAX_WIDGET_ON_BOARD];
00142 } sic_widget_board_t;
00143 
00144 /* Communication board */
00145 static int s_comm_board_id = -1;
00146 static char s_comm_shm_name[SIC_MAX_SHM_NAME];
00147 static sic_comm_board_t *s_comm_board = NULL;
00148 static sic_comm_board_t *s_sem_comm_board = NULL;
00149 
00150 /* Widget board */
00151 static char s_widget_shm_name[SIC_MAX_SHM_NAME];
00152 static sic_widget_board_t *s_widget_board = NULL;
00153 
00154 /* Flag for Ctrl+C */
00155 static int s_ctrlc_handled = 0;
00156 
00157 /***************************************************************************** 
00158  *                        Internal function bodies                           * 
00159  *****************************************************************************/
00160 
00161 #ifdef cygwin
00162 
00163 int shm_open( const char *name, int oflag, mode_t mode)
00164 {
00165     static int s_first_call = 1;
00166     int fd;
00167     char shm_name[PATH_MAX + 20] = "/dev/shm/";
00168 
00169     if (s_first_call) {
00170         struct stat tmp;
00171         if (stat( "/dev", &tmp))
00172             if (mkdir( "/dev", 0777))
00173                 sic_perror( "mkdir");
00174         if (stat( shm_name, &tmp))
00175             if (mkdir( shm_name, 0777))
00176                 sic_perror( "mkdir");
00177         s_first_call = 0;
00178     }
00179 
00180     /* skip opening slash */
00181     if (*name == '/')
00182         ++name;
00183 
00184     /* create special shared memory file name and leave enough space to
00185        cause a path/name error if name is too long */
00186     strlcpy( shm_name + 9, name, PATH_MAX + 10);
00187 
00188     fd = open( shm_name, oflag, mode);
00189 
00190     if (fd != -1) {
00191         /* once open we must add FD_CLOEXEC flag to file descriptor */
00192         int flags = fcntl( fd, F_GETFD, 0);
00193 
00194         if (flags >= 0) {
00195             flags |= FD_CLOEXEC;
00196             flags = fcntl( fd, F_SETFD, flags);
00197         }
00198 
00199         /* on failure, just close file and give up */
00200         if (flags == -1) {
00201             sic_perror( "fcntl");
00202             close( fd);
00203             fd = -1;
00204         }
00205     } else
00206         sic_perror( "open");
00207 
00208     return fd;
00209 }
00210 
00211 int shm_unlink( const char *name)
00212 {
00213     int rc;
00214     char shm_name[PATH_MAX + 20] = "/dev/shm/";
00215 
00216     /* skip opening slash */
00217     if (*name == '/')
00218         ++name;
00219 
00220     /* create special shared memory file name and leave enough space to
00221        cause a path/name error if name is too long */
00222     strlcpy( shm_name + 9, name, PATH_MAX + 10);
00223 
00224     rc = unlink( shm_name);
00225 
00226     return rc;
00227 }
00228 
00229 #endif /* cygwin */
00230 
00231 static int sic_shm_create( const char* name, int size)
00232 {
00233 #ifndef WIN32
00234     int shm_id;
00235 
00236 #ifdef GAG_SYSV
00237     shm_id = shmget( IPC_PRIVATE, size, 0600);
00238 
00239     if (shm_id == -1) {
00240         sic_perror( "shmget");
00241     }
00242 
00243 #else /* GAG_SYSV */
00244     shm_id = shm_open( name, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG);
00245     if (shm_id == -1) {
00246         sic_perror( "shm_open");
00247     }
00248 
00249 #ifndef DONT_SET_CLOSE_ON_EXEC_TO_ZERO
00250     if (fcntl( shm_id, F_SETFD, 0) == -1) {
00251         sic_perror( "fcntl");
00252     }
00253 #endif /* DONT_SET_CLOSE_ON_EXEC_TO_ZERO */
00254 
00255     if (ftruncate( shm_id, size) == -1) {
00256         sic_perror( "ftruncate");
00257     }
00258 #endif /* GAG_SYSV */
00259 
00260     return shm_id;
00261 #else /* WIN32 */
00262     return 0;
00263 #endif /* WIN32 */
00264 }
00265 
00266 static void sic_shm_destroy( const char* name, int shm_id)
00267 {
00268 #ifndef WIN32
00269 #ifdef GAG_SYSV
00270     if (shmctl( shm_id, IPC_RMID, NULL) == -1) {
00271         sic_perror( "shmctl");
00272     }
00273 
00274 #else /* GAG_SYSV */
00275     if (close( shm_id) == -1) {
00276         sic_perror( "close");
00277     }
00278 
00279     if (shm_unlink( name) == -1) {
00280         sic_perror( "shm_unlink");
00281     }
00282 #endif /* GAG_SYSV */
00283 #endif /* WIN32 */
00284 }
00285 
00286 static void* sic_shm_attach( int shm_id, int size)
00287 {
00288     void* addr = NULL;
00289 
00290 #ifndef WIN32
00291 #ifdef GAG_SYSV
00292     addr = shmat( shm_id, (char *)NULL, 0);
00293     if ((long)addr == -1) {
00294         sic_perror( "shmat");
00295     }
00296 
00297 #else /* GAG_SYSV */
00298     addr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_id, 0);
00299     if (addr == MAP_FAILED) {
00300         sic_perror( "mmap");
00301     }
00302 #endif /* GAG_SYSV */
00303 #endif /* WIN32 */
00304 
00305     return addr;
00306 }
00307 
00308 static void sic_shm_detach( void *addr, int size)
00309 {
00310 #ifndef WIN32
00311 #ifdef GAG_SYSV
00312     if (shmdt( addr) == -1) {
00313         sic_perror( "shmdt");
00314     }
00315 
00316 #else /* GAG_SYSV */
00317     if (munmap( addr, size) == -1) {
00318         sic_perror( "munmap");
00319     }
00320 #endif /* GAG_SYSV */
00321 #endif /* WIN32 */
00322 }
00323 
00324 static void sic_sem_open( sic_sem_t *sem)
00325 {
00326 #ifndef WIN32
00327 #ifndef GAG_SYSV
00328 #ifdef SIC_USE_SEM_OPEN
00329     static char sem_name[SIC_MAX_SEM_NAME_FOR_PORTABILITY];
00330     static int count = 0;
00331 
00332 #ifdef SIC_DEBUG_COMM
00333     if (s_comm_board == NULL)
00334         return;
00335 #endif /* SIC_DEBUG_COMM */
00336 
00337     sprintf( sem_name, "/SIC_%d_%d", sic_get_master_task_id( ), ++count);
00338     sem_t *ret = sem_open( sem_name, 0);
00339     if (ret == (sem_t *)SEM_FAILED) {
00340         sic_perror( "sem_open");
00341     }
00342     SIC_SEM_ID(sem) = ret;
00343 #endif /* SIC_USE_SEM_OPEN */
00344 #endif /* GAG_SYSV */
00345 #endif /* WIN32 */
00346 }
00347 
00348 static void sic_sem_create( sic_sem_t *sem, unsigned int initial_value)
00349 {
00350 #if defined(WIN32)
00351     SIC_SEM_ID(sem) = CreateSemaphore( NULL, initial_value, 1, NULL);
00352     if (SIC_SEM_ID(sem) == NULL) {
00353         sic_perror( "CreateSemaphore");
00354     }
00355 #elif defined(GAG_SYSV)
00356     SIC_SEM_ID(sem) = semget( IPC_PRIVATE, 1, S_IRUSR | S_IWUSR);
00357     if (SIC_SEM_ID(sem) == -1) {
00358         sic_perror( "semget");
00359     }
00360 
00361     if (semctl( SIC_SEM_ID(sem), 0, SETVAL, initial_value) == -1) {
00362         sic_perror( "semctl");
00363     }
00364 
00365 #else /* GAG_SYSV */
00366 #ifdef SIC_USE_SEM_OPEN
00367     static char sem_name[SIC_MAX_SEM_NAME_FOR_PORTABILITY];
00368     static int count = 0;
00369 
00370     sprintf( sem_name, "/SIC_%d_%d", sic_get_master_task_id( ), ++count);
00371     sem_t *ret = sem_open( sem_name, O_CREAT, S_IRUSR | S_IWUSR, initial_value);
00372     if (ret == (sem_t *)SEM_FAILED) {
00373         sic_perror( "sem_open");
00374     }
00375     SIC_SEM_ID(sem) = ret;
00376     strncpy( sem->name, sem_name, SIC_MAX_SEM_NAME_FOR_PORTABILITY);
00377 #else /* SIC_USE_SEM_OPEN */
00378     if (sem_init( SIC_SEM_ID(sem), 1, initial_value) == -1) {
00379         sic_perror( "sem_init");
00380     }
00381 #endif /* SIC_USE_SEM_OPEN */
00382 #endif /* GAG_SYSV */
00383 }
00384 
00385 static void sic_sem_close( sic_sem_t *sem)
00386 {
00387 #ifdef SIC_DEBUG_COMM
00388     if (s_comm_board == NULL)
00389         return;
00390 #endif /* SIC_DEBUG_COMM */
00391 
00392 #if defined(WIN32)
00393     if (CloseHandle( SIC_SEM_ID(sem)) == FALSE) {
00394         sic_perror( "CloseHandle");
00395     }
00396 #elif defined(SIC_USE_SEM_OPEN)
00397 #ifndef cygwin
00398     if (sem_close( SIC_SEM_ID(sem)) == -1) {
00399         sic_perror( "sem_close");
00400     }
00401 #endif /* cygwin */
00402 #endif
00403 }
00404 
00405 static void sic_sem_destroy( sic_sem_t *sem)
00406 {
00407 #ifdef SIC_DEBUG_COMM
00408     if (s_comm_board == NULL)
00409         return;
00410 #endif /* SIC_DEBUG_COMM */
00411 
00412     sic_sem_close( sem);
00413 #if defined(WIN32)
00414 #elif defined(GAG_SYSV)
00415     if (semctl( SIC_SEM_ID(sem), 0, IPC_RMID) == -1) {
00416         sic_perror( "semctl");
00417     }
00418 #elif defined(SIC_USE_SEM_OPEN)
00419 #ifndef cygwin
00420     if (sem_unlink( sem->name) == -1) {
00421         sic_perror( "sem_unlink");
00422     }
00423 #else /* cygwin */
00424     if (sem_close( SIC_SEM_ID(sem)) == -1) {
00425         sic_perror( "sem_close");
00426     }
00427 #endif /* cygwin */
00428 #else
00429     if (sem_destroy( SIC_SEM_ID(sem)) == -1) {
00430         sic_perror( "sem_destroy");
00431     }
00432 #endif /* GAG_SYSV */
00433 }
00434 
00435 static void sic_sem_post( sic_sem_t *sem)
00436 {
00437 #if defined(GAG_SYSV)
00438     struct sembuf sops;
00439 #endif
00440 
00441 #ifdef SIC_DEBUG_COMM
00442     if (s_comm_board == NULL)
00443         return;
00444 #endif /* SIC_DEBUG_COMM */
00445 
00446 #if defined(WIN32)
00447     if (!ReleaseSemaphore( SIC_SEM_ID(sem), 1, NULL)) {
00448         sic_perror( "ReleaseSemaphore");
00449     }
00450 #elif defined(GAG_SYSV)
00451     sops.sem_num = 0;
00452     sops.sem_op = 1;
00453     sops.sem_flg = 0;
00454 
00455     if (semop( SIC_SEM_ID(sem), &sops, 1) == -1) {
00456         sic_perror( "semop");
00457     }
00458 
00459 #else /* GAG_SYSV */
00460     if (sem_post( SIC_SEM_ID(sem)) == -1) {
00461         sic_perror( "sem_post");
00462     }
00463 #endif /* GAG_SYSV */
00464 }
00465 
00466 static void sic_sem_wait( sic_sem_t *sem)
00467 {
00468 #if defined(GAG_SYSV)
00469     struct sembuf sops;
00470 #endif
00471 
00472 #ifdef SIC_DEBUG_COMM
00473     if (s_comm_board == NULL)
00474         return;
00475 #endif /* SIC_DEBUG_COMM */
00476 
00477 #if defined(WIN32)
00478     if (WaitForSingleObject( SIC_SEM_ID(sem), INFINITE) != WAIT_OBJECT_0) {
00479         sic_perror( "WaitForSingleObject");
00480     }
00481 #elif defined(GAG_SYSV)
00482     sops.sem_num = 0;
00483     sops.sem_op = -1;
00484     sops.sem_flg = 0;
00485 
00486     while (semop( SIC_SEM_ID(sem), &sops, 1) == -1) {
00487         if (errno == EINTR)
00488             errno = 0;
00489         else
00490             sic_perror( "semop");
00491     }
00492 #else /* GAG_SYSV */
00493     while (sem_wait( SIC_SEM_ID(sem)) == -1) {
00494         if (errno == EINTR)
00495             errno = 0;
00496         else
00497             sic_perror( "sem_wait");
00498     }
00499 #endif /* GAG_SYSV */
00500 }
00501 
00502 static int sic_sem_timed_wait( sic_sem_t *sem, int timeout)
00503 {
00504     int ret = 0;
00505 
00506 #ifdef SIC_DEBUG_COMM
00507     if (s_comm_board == NULL)
00508         return 0;
00509 #endif /* SIC_DEBUG_COMM */
00510 
00511     if (timeout == -1) {
00512         sic_sem_wait( sem);
00513         return 0;
00514     } else {
00515 #if defined(WIN32)
00516         DWORD wait = WaitForSingleObject( SIC_SEM_ID(sem), timeout);
00517         if (wait != WAIT_OBJECT_0) {
00518             if (wait == WAIT_TIMEOUT)
00519                 ret = -1;
00520             else
00521                 sic_perror( "WaitForSingleObject");
00522         }
00523 #elif defined(GAG_SYSV) || defined(darwin)
00524         sic_sem_wait( sem);
00525 #else /* defined(GAG_SYSV) || defined(darwin) */
00526         struct timespec t;
00527 
00528         clock_gettime( CLOCK_REALTIME, &t);
00529 
00530         /* seconds */
00531         time_t nb_sec = timeout / 1000;
00532         /* nano seconds */
00533         long nb_nsec = (timeout - nb_sec * 1000) * 1000000L;
00534         if (nb_nsec + t.tv_nsec > 1000000000L) {
00535             nb_sec++;
00536             nb_nsec -= 1000000000L;
00537         }
00538         t.tv_sec += nb_sec;
00539         t.tv_nsec += nb_nsec;
00540 
00541         ret = sem_timedwait( SIC_SEM_ID(sem), &t);
00542         if (ret == -1) {
00543             if (errno == EINTR || errno == ETIMEDOUT)
00544                 errno = 0;
00545             else
00546                 sic_perror( "sem_timedwait");
00547         }
00548 #endif /* defined(GAG_SYSV) || defined(darwin) */
00549     }
00550     return ret;
00551 }
00552 
00553 static void sic_on_modified_variable( sic_listener_handler_t *h)
00554 {
00555     gag_trace( "<trace> sic_on_modified_variable");
00556     /* no need to call sic_open_widget_board because already done by sic_fire_modified_variable_event */
00557     (*(sic_modified_variable_listener_t)h->listener)( &s_widget_board->modified_widget);
00558 }
00559 
00560 static void sic_on_redraw_prompt( sic_listener_handler_t *h)
00561 {
00562     gag_trace( "<trace> sic_on_redraw_prompt");
00563     (*(sic_redraw_prompt_listener_t)h->listener)( &s_comm_board->command_line);
00564 }
00565 
00566 static void sic_on_event( sic_listener_handler_t *h)
00567 {
00568     switch (h->event_id) {
00569     case SIC_MODIFIED_VARIABLE_EVENT:
00570         sic_on_modified_variable( h);
00571         break;
00572     case SIC_REDRAW_PROMPT_EVENT:
00573         sic_on_redraw_prompt( h);
00574         break;
00575     }
00576 #ifndef WIN32
00577     sic_sem_post( &s_sem_comm_board->listener_acquit);
00578 #endif
00579 }
00580 
00581 static void sic_event_handler( int sig_num)
00582 {
00583     int i;
00584     int event_id = s_comm_board->event_id;
00585 
00586 #ifndef WIN32
00587     signal( sig_num, sic_event_handler);
00588 #endif /* WIN32 */
00589     for (i = 0; i < s_comm_board->listener_count; i++) {
00590         sic_listener_handler_t *h = &s_comm_board->listeners[i];
00591         if (h->event_id == event_id) {
00592             sic_on_event( h);
00593         }
00594     }
00595 }
00596 
00597 static void sic_record_listener( sic_listener_handler_t *widget_handler)
00598 {
00599 #ifdef SIC_DEBUG_COMM
00600     if (s_comm_board == NULL)
00601         return;
00602 #endif /* SIC_DEBUG_COMM */
00603 
00604     sic_sem_wait( &s_sem_comm_board->comm_board_access);
00605 
00606     s_comm_board->listeners[s_comm_board->listener_count++] = *widget_handler;
00607 #ifndef WIN32
00608     signal( widget_handler->sig_num, sic_event_handler);
00609 #endif /* WIN32 */
00610 
00611     sic_sem_post( &s_sem_comm_board->comm_board_access);
00612 }
00613 
00614 static void sic_trigger_listener( sic_listener_handler_t *h)
00615 {
00616 #ifndef WIN32
00617     if (kill( h->task, h->sig_num) == 0)
00618         sic_sem_timed_wait( &s_sem_comm_board->listener_acquit, 1000);
00619 #else /* WIN32 */
00620     sic_on_event( h);
00621 #endif /* WIN32 */
00622 }
00623 
00624 static void sic_trigger_listeners( int event_id)
00625 {
00626     int i;
00627 
00628     sic_sem_wait( &s_sem_comm_board->comm_board_access);
00629 
00630     s_comm_board->event_id = event_id;
00631 
00632     for (i = 0; i < s_comm_board->listener_count; i++) {
00633         sic_listener_handler_t *h = &s_comm_board->listeners[i];
00634         if (h->event_id == event_id)
00635             sic_trigger_listener( h);
00636     }
00637 
00638     sic_sem_post( &s_sem_comm_board->comm_board_access);
00639 }
00640 
00641 static void sic_purge_listeners( task_t task)
00642 {
00643     int i;
00644     int j;
00645 
00646     sic_sem_wait( &s_sem_comm_board->comm_board_access);
00647 
00648     j = 0;
00649     for (i = 0; i < s_comm_board->listener_count; i++) {
00650         sic_listener_handler_t *h = &s_comm_board->listeners[i];
00651         if (h->task != task) {
00652             if (j != i)
00653                 s_comm_board->listeners[j] = *h;
00654             j++;
00655         }
00656     }
00657     s_comm_board->listener_count = j;
00658 
00659     sic_sem_post( &s_sem_comm_board->comm_board_access);
00660 }
00661 
00662 static int sic_is_master( )
00663 {
00664     return s_comm_board_id != -1;
00665 }
00666 
00667 static void sic_kill_all_child_processes( )
00668 {
00669 #ifndef WIN32
00670     signal( SIGCLD, SIG_IGN);           /* Avoid zombies */
00671     signal( SIGTERM, SIG_IGN);          /* don't kill itself */
00672     kill( 0, SIGTERM);
00673     wait( 0);
00674 #endif /* WIN32 */
00675 }
00676 
00677 static void sic_signal_handler( int sig_num)
00678 {
00679     gag_trace( "<trace: signal> sic_signal_handler on %d", sig_num);
00680     sic_do_exit( 1);
00681 }
00682 
00683 static void sic_init_handlers( )
00684 {
00685     atexit( sic_on_exit);
00686 #ifndef WIN32
00687     if (!s_ctrlc_handled)
00688         signal( SIGINT, SIG_IGN);
00689     signal( SIGTTOU, SIG_IGN);
00690 
00691     signal( SIGHUP, sic_signal_handler);
00692     signal( SIGQUIT, sic_signal_handler);
00693     signal( SIGILL, sic_signal_handler);
00694     signal( SIGABRT, sic_signal_handler);
00695     signal( SIGBUS, sic_signal_handler);
00696     signal( SIGFPE, sic_signal_handler);
00697     signal( SIGSEGV, sic_signal_handler);
00698     signal( SIGPIPE, sic_signal_handler);
00699     signal( SIGTERM, sic_signal_handler);
00700     signal( SIGSTOP, sic_signal_handler);
00701     signal( SIGSYS, sic_signal_handler);
00702 #if defined(SIGIO)
00703     signal( SIGIO, sic_signal_handler);
00704 #elif defined(SIGPOLL)
00705     signal( SIGPOLL, sic_signal_handler);
00706 #endif
00707 #endif /* WIN32 */
00708 }
00709 
00718 static int sic_raw_post_command_from( const command_line_t *command_line, int timeout, sic_command_from_t from)
00719 {
00720     int ret;
00721 
00722 #ifdef SIC_DEBUG_COMM
00723     if (s_comm_board == NULL)
00724         return 0;
00725 #endif /* SIC_DEBUG_COMM */
00726 
00727     gag_trace( "<trace: enter> sic_post_command");
00728     ret = sic_sem_timed_wait( &s_sem_comm_board->write_command, timeout);
00729     if (ret == 0) {
00730         /* keep current prompt */
00731         strncpy( (char*)command_line->prompt, s_comm_board->command_line.prompt, PROMPT);
00732         s_comm_board->command_line = *command_line;
00733         s_comm_board->from = from;
00734         gag_trace( "<command: send> \"%s%s\"", command_line->prompt, command_line->line);
00735         sic_sem_post( &s_sem_comm_board->read_command);
00736     }
00737     gag_trace( "<trace: leave> sic_post_command");
00738     return ret;
00739 }
00740 
00741 static void sic_build_command_line( const char* text, command_line_t *command_line)
00742 {
00743     strncpy( command_line->line, text, MAXBUF);
00744     command_line->nc = (int)strlen( text);
00745     command_line->prompt[0] = '\0';
00746     command_line->code = 0;
00747 }
00748 
00749 /***************************************************************************** 
00750  *                             Function bodies                               * 
00751  *****************************************************************************/
00752 
00757 void sic_create_comm_board( )
00758 {
00759     char *trace = getenv( "SIC_COMM_TRACE");
00760     if (trace != NULL) {
00761         gag_trace_open( trace);
00762     }
00763 
00764     gag_trace( "<trace: enter> sic_create_comm_board");
00765     if (s_comm_board_id == -1) {
00766         sprintf( s_comm_shm_name, "/SIC_%d_C", sic_get_current_task_id( ));
00767         s_comm_board_id = sic_shm_create( s_comm_shm_name, sizeof( sic_comm_board_t));
00768         sic_open_comm_board( s_comm_board_id);
00769         s_comm_board->master_task = sic_get_current_task( );
00770         s_comm_board->keyboard_task = SIC_TASK_NULL;
00771         if (gag_trace_get_file_pointer( ) != NULL)
00772             s_comm_board->trace_fd = fileno( gag_trace_get_file_pointer( ));
00773         else
00774             s_comm_board->trace_fd = -1;
00775         sic_sem_create( &s_sem_comm_board->comm_board_access, 1);
00776         sic_sem_create( &s_sem_comm_board->draw_prompt, 0);
00777         sic_sem_create( &s_sem_comm_board->write_command, 0);
00778         sic_sem_create( &s_sem_comm_board->read_command, 0);
00779         sic_sem_create( &s_sem_comm_board->widget_board_access, 1);
00780         sic_sem_create( &s_sem_comm_board->widget_created, 0);
00781         sic_sem_create( &s_sem_comm_board->listener_acquit, 0);
00782         s_comm_board->widget_board_id = -1;
00783         sic_build_command_line( "", &s_comm_board->command_line);
00784         s_comm_board->pushed_command_text[0] = '\0';
00785         s_comm_board->from = -1;
00786         s_comm_board->listener_count = 0;
00787         s_comm_board->event_id = -1;
00788     }
00789     gag_trace( "<trace: leave> sic_create_comm_board");
00790 }
00791 
00795 void sic_destroy_comm_board( )
00796 {
00797     gag_trace( "<trace: enter> sic_destroy_comm_board");
00798 
00799     SIC_ASSERT( "sic_destroy_comm_board called from child process", sic_is_master( ));
00800 
00801     sic_kill_all_child_processes( );
00802     if (s_sem_comm_board != NULL) {
00803         sic_sem_destroy( &s_sem_comm_board->comm_board_access);
00804         sic_sem_destroy( &s_sem_comm_board->draw_prompt);
00805         sic_sem_destroy( &s_sem_comm_board->write_command);
00806         sic_sem_destroy( &s_sem_comm_board->read_command);
00807         sic_sem_destroy( &s_sem_comm_board->widget_board_access);
00808         sic_sem_destroy( &s_sem_comm_board->widget_created);
00809         sic_sem_destroy( &s_sem_comm_board->listener_acquit);
00810         s_sem_comm_board = NULL;
00811     }
00812 
00813     sic_close_comm_board( );
00814 
00815     if (s_comm_board_id >= 0) {
00816         sic_shm_destroy( s_comm_shm_name, s_comm_board_id);
00817         /* do it last for sic_is_master to work */
00818         s_comm_board_id = -1;
00819     }
00820 
00821     gag_trace( "<trace: leave> sic_destroy_comm_board");
00822 }
00823 
00824 #ifndef WIN32
00825 /*
00826  * Fork a process.
00827  */
00828 static pid_t sic_fork( )
00829 {
00830     pid_t pid;
00831 
00832     gag_trace( "<trace: fork>");
00833 
00834     /* flush the associated standard I/O streams
00835        to prevent duplicated outputs */
00836     fflush( NULL);
00837 
00838     pid = fork( );
00839     if (pid < 0) {
00840         sic_perror( "fork");
00841     } else if (pid) {
00842         gag_trace( "<trace: fork> process %d created", pid);
00843     } else {
00844         gag_trace( "<trace: fork> child starting");
00845     }
00846     return pid;
00847 }
00848 #endif /* WIN32 */
00849 
00853 char **sic_get_static_argv( )
00854 {
00855     static char *s_argv[MAX_ARGC];
00856     static char s_argv_buf[MAX_ARGC][MAX_ARGV];
00857     int i;
00858 
00859     /* make argv pointing on allocated buffers */
00860     for (i = 0; i < MAX_ARGC; i++)
00861         s_argv[i] = s_argv_buf[i];
00862 
00863     return s_argv;
00864 }
00865 
00873 int sic_execvp( char *argv[])
00874 {
00875 #ifndef WIN32
00876 #ifdef SIC_DEBUG_COMM
00877     char gdb_cmd_file[MAX_ARGV];
00878     FILE *fp;
00879     int i;
00880     static char *exec_argv[MAX_ARGC];
00881     static char exec_argv_buf[MAX_ARGC][MAX_ARGV];
00882 #endif /* SIC_DEBUG_COMM */
00883     char *app_name = argv[0];
00884 
00885     gag_trace( "<trace: exec> %s", app_name);
00886 
00887 #ifdef SIC_DEBUG_COMM
00888     if (getenv( "SIC_DEBUG_GDB") == NULL)
00889 #endif /* SIC_DEBUG_COMM */
00890 
00891         return execvp( argv[0], argv);
00892 
00893 #ifdef SIC_DEBUG_COMM
00894     /* don't use sic_get_static_argv( ) because it can be use by the caller */
00895     /* make argv pointing on allocated buffers */
00896     for (i = 0; i < MAX_ARGC; i++)
00897         exec_argv[i] = exec_argv_buf[i];
00898 
00899     /* create gdb command file */
00900     sprintf( gdb_cmd_file, ".gdb_%s", app_name);
00901     fp = fopen( gdb_cmd_file, "w");
00902     fprintf( fp, "set args");
00903     for (i = 1; argv[i] != NULL; i++) {
00904         fprintf( fp, " \"%s\"", argv[i]);
00905     }
00906     fprintf( fp, "\n");
00907     fclose( fp);
00908 
00909     /* create command line with call to gdb */
00910     i = 0;
00911     sprintf( exec_argv[i++], "xterm");
00912     sprintf( exec_argv[i++], "-T");
00913     sprintf( exec_argv[i++], app_name);
00914     sprintf( exec_argv[i++], "-e");
00915     sprintf( exec_argv[i++], "gdb");
00916     sprintf( exec_argv[i++], "-x");
00917     sprintf( exec_argv[i++], gdb_cmd_file);
00918     sprintf( exec_argv[i++], app_name);
00919     exec_argv[i++] = NULL;
00920     if (i >= MAX_ARGC) {
00921         fprintf( stderr, "E-SIC, too much arguments, exiting\n");
00922         sic_do_exit( 1);
00923     }
00924 
00925     /* show original command line */
00926     printf( "I-SIC, Launching:");
00927     for (i = 0; argv[i] != NULL; i++)
00928         printf( " %s", argv[i]);
00929     printf( "\n");
00930 
00931     return execvp( exec_argv[0], exec_argv);
00932 #endif /* SIC_DEBUG_COMM */
00933 #else /* WIN32 */
00934     return 0;
00935 #endif /* WIN32 */
00936 }
00937 
00944 task_t sic_launch( int (*start_entry)( void *), void *data)
00945 {
00946 #ifndef WIN32
00947     pid_t pid = sic_fork( );
00948 
00949     if (pid == 0) {
00950         /* child process */
00951         if ((*start_entry)( data) == -1)
00952             pid = - 1;
00953     }
00954 
00955     return pid;
00956 #else /* WIN32 */
00957     DWORD dwThreadId; 
00958     HANDLE hthrd;
00959 
00960     hthrd = CreateThread( 
00961         NULL,                        // no security attributes 
00962         0,                           // use default stack size  
00963         (LPTHREAD_START_ROUTINE) start_entry, // thread function 
00964         data,                        // argument to thread function 
00965         0,                           // use default creation flags 
00966         &dwThreadId);                // returns the thread identifier 
00967 
00968     // Check the return value for success. 
00969 
00970     if (hthrd == NULL) 
00971         sic_perror( "CreateThread");
00972 
00973     return hthrd;
00974 #endif /* WIN32 */
00975 }
00976 
00983 int sic_terminate( task_t task)
00984 {
00985 #ifndef WIN32
00986     if (kill( task, SIGTERM))
00987         return -1;
00988     if (waitpid( task, NULL, 0) == -1)
00989         return -1;
00990 #else /* WIN32 */
00991     if (!TerminateThread( task, 0)) {
00992         sic_pwarning( "TerminateThread");
00993         return -1;
00994     }
00995 #endif /* WIN32 */
00996     return 0;
00997 }
00998 
01002 void sic_on_exit( )
01003 {
01004     static int recur_level = 0;
01005 
01006     gag_trace( "<trace: sic_on_exit>");
01007     if (!recur_level) {
01008         recur_level++;
01009         if (sic_is_master( ))
01010             sic_destroy_comm_board( );
01011         else
01012             sic_close_comm_board( );
01013     }
01014 
01015     gag_trace( "<trace: exit>");
01016     gag_trace_close( );
01017 }
01018 
01024 void sic_do_exit( int status)
01025 {
01026     gag_trace( "<trace: sic_do_exit>");
01027 
01028     exit( status);
01029 }
01030 
01034 int sic_get_comm_id( )
01035 {
01036     return s_comm_board_id;
01037 }
01038 
01046 int sic_open_comm_board( int comm_board_id)
01047 {
01048     if (comm_board_id == -1) {
01049         SIC_ASSERT( "sic_open_comm_board with bad id", 0);
01050         return -1;
01051     }
01052 
01053     sic_init_handlers( );
01054     
01055     /* negative comm_board_id can be used for debugging purpose */
01056     if (s_comm_board == NULL
01057 #ifdef SIC_DEBUG_COMM
01058         && comm_board_id >= 0
01059 #endif /* SIC_DEBUG_COMM */
01060         ) {
01061 #ifndef WIN32
01062         s_comm_board = sic_shm_attach( comm_board_id, sizeof( sic_comm_board_t));
01063 #else /* WIN32 */
01064         static sic_comm_board_t single_process_comm_board;
01065 
01066         s_comm_board = &single_process_comm_board;
01067 #endif/* WIN32 */
01068         s_sem_comm_board = s_comm_board;
01069 
01070         if (!sic_is_master( )) {
01071             if (s_comm_board->trace_fd >= 0)
01072                 gag_trace_set_file_pointer( fdopen( s_comm_board->trace_fd, "w"));
01073 
01074 #ifdef SIC_USE_SEM_OPEN
01075             static sic_comm_board_t process_local_sem_comm_board;
01076             s_sem_comm_board = &process_local_sem_comm_board;
01077 #endif /* SIC_USE_SEM_OPEN */
01078 
01079             sic_sem_open( &s_sem_comm_board->comm_board_access);
01080             sic_sem_open( &s_sem_comm_board->draw_prompt);
01081             sic_sem_open( &s_sem_comm_board->write_command);
01082             sic_sem_open( &s_sem_comm_board->read_command);
01083             sic_sem_open( &s_sem_comm_board->widget_board_access);
01084             sic_sem_open( &s_sem_comm_board->widget_created);
01085             sic_sem_open( &s_sem_comm_board->listener_acquit);
01086         }
01087     }
01088     gag_trace( "<trace> sic_open_comm_board");
01089     return 0;
01090 }
01091 
01095 void sic_close_comm_board( )
01096 {
01097     gag_trace( "<trace> sic_close_comm_board");
01098     if (s_comm_board != NULL) {
01099 #ifndef WIN32
01100         sync( ); /* flush disks */
01101 #endif /* WIN32 */
01102         sic_destroy_widget_board( );
01103         if (s_sem_comm_board != NULL) {
01104             sic_purge_listeners( sic_get_current_task( ));
01105             sic_sem_close( &s_sem_comm_board->comm_board_access);
01106             sic_sem_close( &s_sem_comm_board->draw_prompt);
01107             sic_sem_close( &s_sem_comm_board->write_command);
01108             sic_sem_close( &s_sem_comm_board->read_command);
01109             sic_sem_close( &s_sem_comm_board->widget_board_access);
01110             sic_sem_close( &s_sem_comm_board->widget_created);
01111             sic_sem_close( &s_sem_comm_board->listener_acquit);
01112             s_sem_comm_board = NULL;
01113         }
01114         sic_shm_detach( s_comm_board, sizeof( sic_comm_board_t));
01115         s_comm_board = NULL;
01116     }
01117 }
01118 
01125 task_id_t sic_get_task_id( task_t task)
01126 {
01127 #ifndef WIN32
01128     return (task_id_t)task;
01129 #else
01130     return (task_id_t)(long long)task;
01131 #endif
01132 }
01133 
01139 task_t sic_get_master_task( )
01140 {
01141 #ifdef SIC_DEBUG_COMM
01142     if (s_comm_board == NULL)
01143         return (task_t)0;
01144 #endif /* SIC_DEBUG_COMM */
01145 
01146     return s_comm_board->master_task;
01147 }
01148 
01154 task_id_t sic_get_master_task_id( )
01155 {
01156     return sic_get_task_id( sic_get_master_task( ));
01157 }
01158 
01164 task_t sic_get_current_task( )
01165 {
01166 #ifndef WIN32
01167     return getpid( );
01168 #else
01169     return GetCurrentThread( );
01170 #endif
01171 }
01172 
01178 task_id_t sic_get_current_task_id( )
01179 {
01180     return sic_get_task_id( sic_get_current_task( ));
01181 }
01182 
01188 void sic_set_ctrlc_handled( int handled)
01189 {
01190     s_ctrlc_handled = handled;
01191 }
01192 
01196 void sic_send_ctrlc( )
01197 {
01198 #ifndef WIN32
01199     kill( sic_get_master_task( ), SIGINT);
01200 #else /* WIN32 */
01201     sic_do_exit( 0);
01202 #endif /* WIN32 */
01203 }
01204 
01208 void sic_post_prompt( const command_line_t *command_line)
01209 {
01210     gag_trace( "<trace> sic_post_prompt");
01211     s_comm_board->command_line = *command_line;
01212     sic_sem_post( &s_sem_comm_board->draw_prompt);
01213 }
01214 
01222 int sic_wait_prompt( command_line_t *command_line, int timeout)
01223 {
01224     int ret;
01225 
01226 #ifdef SIC_DEBUG_COMM
01227     if (s_comm_board == NULL)
01228         return 0;
01229 #endif /* SIC_DEBUG_COMM */
01230 
01231     gag_trace( "<trace: enter> sic_wait_prompt");
01232     ret = sic_sem_timed_wait( &s_sem_comm_board->draw_prompt, timeout);
01233     if (ret == 0) {
01234         *command_line = s_comm_board->command_line;
01235     }
01236     gag_trace( "<trace: leave> sic_wait_prompt");
01237     return ret;
01238 }
01239 
01245 void sic_get_current_prompt( char prompt[])
01246 {
01247     strncpy( prompt, s_comm_board->command_line.prompt, PROMPT);
01248 }
01249 
01256 int sic_push_command_text( const char *text)
01257 {
01258     gag_trace( "<trace: enter> sic_push_command_text");
01259 
01260     if (s_comm_board->pushed_command_text[0]) {
01261         gag_trace( "<trace: leave> sic_push_command_text return error");
01262         return -1;
01263     }
01264 
01265     strncpy( s_comm_board->pushed_command_text, text, MAXBUF);
01266     gag_trace( "<command: push> \"%s\"", text);
01267     sic_sem_post( &s_sem_comm_board->read_command);
01268 
01269     gag_trace( "<trace: leave> sic_push_command_text");
01270     return 0;
01271 }
01272 
01280 int sic_post_command_from( const command_line_t *command_line, sic_command_from_t from)
01281 {
01282     return sic_raw_post_command_from( command_line, 2000, from);
01283 }
01284 
01291 int sic_post_command( const command_line_t *command_line)
01292 {
01293     return sic_post_command_from( command_line, SIC_DEFAULT);
01294 }
01295 
01301 void sic_post_command_from_prompt( const command_line_t *command_line)
01302 {
01303     sic_raw_post_command_from( command_line, -1, SIC_KEYBOARD);
01304 }
01305 
01313 int sic_post_command_text_from( const char *text, sic_command_from_t from)
01314 {
01315     command_line_t command_line;
01316     
01317     sic_build_command_line( text, &command_line);
01318 
01319     return sic_post_command_from( &command_line, from);
01320 }
01321 
01328 int sic_post_command_text( const char *text)
01329 {
01330     return sic_post_command_text_from( text, SIC_DEFAULT);
01331 }
01332 
01339 int sic_post_command_va( const char *args, va_list l)
01340 {
01341     char command[MAXBUF];
01342     vsprintf( command, args, l);
01343 
01344     return sic_post_command_text( command);
01345 }
01346 
01353 int sic_post_command_args( const char *args, ...)
01354 {
01355     int ret;
01356     va_list l;
01357 
01358     va_start( l, args);
01359     ret = sic_post_command_va( args, l);
01360     va_end( l);
01361 
01362     return ret;
01363 }
01364 
01371 void sic_wait_command( command_line_t *command_line, sic_command_from_t *from)
01372 {
01373     gag_trace( "<trace: enter> sic_wait_command");
01374     if (!s_comm_board->pushed_command_text[0])
01375         sic_sem_post( &s_sem_comm_board->write_command);
01376     sic_sem_wait( &s_sem_comm_board->read_command);
01377     if (!s_comm_board->pushed_command_text[0]) {
01378         *command_line = s_comm_board->command_line;
01379         *from = s_comm_board->from;
01380     } else {
01381         sic_build_command_line( s_comm_board->pushed_command_text, command_line);
01382         *from = SIC_DEFAULT;
01383         s_comm_board->pushed_command_text[0] = '\0';
01384     }
01385     gag_trace( "<command: receive> \"%s%s\"", command_line->prompt, command_line->line);
01386 
01387     gag_trace( "<trace: leave> sic_wait_command");
01388 }
01389 
01394 void sic_create_widget_board( )
01395 {
01396     gag_trace( "<trace> sic_create_widget_board");
01397     if (s_comm_board->widget_board_id < 0) {
01398         sprintf( s_widget_shm_name, "/SIC_%d_W", sic_get_current_task_id( ));
01399         s_comm_board->widget_board_id = sic_shm_create( s_widget_shm_name, sizeof( sic_widget_board_t));
01400     }
01401     sic_open_widget_board( );
01402     s_widget_board->widget_count = 0;
01403 }
01404 
01412 void sic_set_widget_global_infos( const char window_title[], const char help_filename[], const char returned_command[])
01413 {
01414     strcpy( s_widget_board->window_title, window_title);
01415     strcpy( s_widget_board->help_filename, help_filename);
01416     strcpy( s_widget_board->returned_command, returned_command);
01417 }
01418 
01424 void sic_set_widget_returned_command( const char returned_command[])
01425 {
01426 #ifdef SIC_DEBUG_COMM
01427     if (s_comm_board == NULL)
01428         return;
01429 #endif /* SIC_DEBUG_COMM */
01430 
01431     strcpy( s_widget_board->returned_command, returned_command);
01432 }
01433 
01439 void sic_get_widget_returned_command( char returned_command[])
01440 {
01441     strcpy( returned_command, s_widget_board->returned_command);
01442 }
01443 
01449 void sic_set_widget_returned_code( int code)
01450 {
01451 #ifdef SIC_DEBUG_COMM
01452     if (s_comm_board == NULL)
01453         return;
01454 #endif /* SIC_DEBUG_COMM */
01455 
01456     s_widget_board->returned_code = code;
01457 }
01458 
01464 int sic_get_widget_returned_code( )
01465 {
01466     return s_widget_board->returned_code;
01467 }
01468 
01474 void sic_add_modified_variable_listener( sic_modified_variable_listener_t l)
01475 {
01476     sic_listener_handler_t h = {
01477         (task_t)NULL,
01478         SIC_MODIFIED_VARIABLE_EVENT,
01479         NULL,
01480 #ifndef WIN32
01481         SIGUSR2
01482 #else /* WIN32 */
01483         0
01484 #endif /* WIN32 */
01485     };
01486     h.task = sic_get_current_task( );
01487     h.listener = l;
01488     sic_record_listener( &h);
01489 }
01490 
01496 void sic_fire_modified_variable_event( const sic_widget_def_t *widget)
01497 {
01498     gag_trace( "<trace: enter> sic_fire_modified_variable_event");
01499     sic_open_widget_board( );
01500     s_widget_board->modified_widget = *widget;
01501     sic_trigger_listeners( SIC_MODIFIED_VARIABLE_EVENT);
01502     sic_close_widget_board( );
01503     gag_trace( "<trace: leave> sic_fire_modified_variable_event");
01504 }
01505 
01511 void sic_add_redraw_prompt_listener( sic_redraw_prompt_listener_t l)
01512 {
01513     sic_listener_handler_t h = {
01514         (task_t)NULL,
01515         SIC_REDRAW_PROMPT_EVENT,
01516         NULL,
01517 #ifndef WIN32
01518         SIGUSR2
01519 #else /* WIN32 */
01520         0
01521 #endif /* WIN32 */
01522     };
01523     h.task = sic_get_current_task( );
01524     h.listener = l;
01525     sic_record_listener( &h);
01526 }
01527 
01533 void sic_fire_redraw_prompt_event( const command_line_t *command_line)
01534 {
01535     gag_trace( "<trace: enter> sic_fire_redraw_prompt_event");
01536     s_comm_board->command_line = *command_line;
01537     sic_trigger_listeners( SIC_REDRAW_PROMPT_EVENT);
01538     gag_trace( "<trace: leave> sic_fire_redraw_prompt_event");
01539 }
01540 
01544 void sic_suspend_prompt( )
01545 {
01546     fprintf( stderr, "%s\n", s_comm_board->command_line.line);
01547 }
01548 
01555 int sic_add_widget_def( sic_widget_def_t *def)
01556 {
01557     if (s_widget_board->widget_count >= SIC_MAX_WIDGET_ON_BOARD)
01558         return -1;
01559 
01560     s_widget_board->widgets[s_widget_board->widget_count++] = *def;
01561 
01562     return 0;
01563 }
01564 
01571 void sic_set_widget_def( int index, const sic_widget_def_t *widget)
01572 {
01573     s_widget_board->widgets[index] = *widget;
01574 }
01575 
01579 void sic_destroy_widget_board( )
01580 {
01581     gag_trace( "<trace> sic_destroy_widget_board");
01582     if (s_widget_board != NULL) {
01583         sic_shm_detach( s_widget_board, sizeof( sic_widget_board_t));
01584         s_widget_board = NULL;
01585     }
01586     /* destroy share memory from master */
01587     if (sic_is_master( ) && s_comm_board->widget_board_id >= 0) {
01588         sic_shm_destroy( s_widget_shm_name, s_comm_board->widget_board_id);
01589         s_comm_board->widget_board_id = -1;
01590     }
01591 }
01592 
01599 int sic_open_widget_board( )
01600 {
01601 #ifdef SIC_DEBUG_COMM
01602     if (s_comm_board == NULL)
01603         return 0;
01604 #endif /* SIC_DEBUG_COMM */
01605 
01606     gag_trace( "<trace: enter> sic_open_widget_board");
01607     sic_sem_wait( &s_sem_comm_board->widget_board_access);
01608     if (s_widget_board == NULL) {
01609 #ifndef WIN32
01610         s_widget_board = sic_shm_attach( s_comm_board->widget_board_id, sizeof( sic_widget_board_t));
01611 #else /* WIN32 */
01612         static sic_widget_board_t single_process_widget_board;
01613 
01614         s_widget_board = &single_process_widget_board;
01615 #endif/* WIN32 */
01616     }
01617     gag_trace( "<trace: leave> sic_open_widget_board");
01618     return s_widget_board->widget_count;
01619 }
01620 
01628 void sic_get_widget_global_infos( char window_title[], char help_filename[], char returned_command[])
01629 {
01630 #ifdef SIC_DEBUG_COMM
01631     if (s_comm_board == NULL)
01632         return;
01633 #endif /* SIC_DEBUG_COMM */
01634 
01635     strcpy( window_title, s_widget_board->window_title);
01636     strcpy( help_filename, s_widget_board->help_filename);
01637     strcpy( returned_command, s_widget_board->returned_command);
01638 }
01639 
01646 void sic_get_widget_def( int index, sic_widget_def_t *widget)
01647 {
01648     *widget = s_widget_board->widgets[index];
01649 }
01650 
01654 void sic_close_widget_board( )
01655 {
01656 #ifdef SIC_DEBUG_COMM
01657     if (s_comm_board == NULL)
01658         return;
01659 #endif /* SIC_DEBUG_COMM */
01660 
01661     gag_trace( "<trace> sic_close_widget_board");
01662     sic_sem_post( &s_sem_comm_board->widget_board_access);
01663 }
01664 
01668 void sic_post_widget_created( )
01669 {
01670     gag_trace( "<trace> sic_post_widget_created");
01671     sic_sem_post( &s_sem_comm_board->widget_created);
01672 }
01673 
01677 void sic_wait_widget_created( )
01678 {
01679     gag_trace( "<trace: enter> sic_wait_widget_created");
01680     sic_sem_wait( &s_sem_comm_board->widget_created);
01681     gag_trace( "<trace: leave> sic_wait_widget_created");
01682 }
01683 

Generated on Tue Mar 13 15:15:40 2007 for SIC by  doxygen 1.5.1