00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <config.h>
00037
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 #include <sys/types.h>
00041 #include <sys/time.h>
00042 #include <sys/wait.h>
00043 #include <fcntl.h>
00044 #include <pthread.h>
00045 #include <signal.h>
00046 #include <sys/types.h>
00047 #include <sys/wait.h>
00048 #include <unistd.h>
00049 #include <signal.h>
00050 #include <memory.h>
00051
00052 #include <gtk/gtk.h>
00053 #include <gdk/gdkkeysyms.h>
00054
00055 #include <liberregxml/erregapi.h>
00056 #include <liberipc/eripctoolbar.h>
00057 #include <libermanifest/ermanifest.h>
00058
00059 #include "contentListerLog.h"
00060 #include "erbusy.h"
00061 #include "displayUpdate.h"
00062 #include "programManager.h"
00063 #include "regValue.h"
00064 #include "button.h"
00065 #include "erConnect.h"
00066 #include "erMSDisk.h"
00067 #include "system.h"
00068 #include "gtkPincodeScreen.h"
00069 #include "control.h"
00070 #include "toolbar.h"
00071 #include "languages.h"
00072 #include "timedids.h"
00073
00074 static GArray *g_xClientInfo = NULL;
00075 static Window g_myWin;
00076 static GHashTable *g_programInfo = NULL;
00077 static GHashTable *g_extensionInfo = NULL;
00078 static gchar g_uaOnTop[UAID_MAX_SIZE];
00079 static gchar g_lastStartedUa[UAID_MAX_SIZE];
00080
00081
00082 static int pm_XErrorHandler(Display *display, XErrorEvent *event);
00083 static int pm_UpdateState();
00084 static gboolean pm_InitProgramTable(void);
00085 static void pm_InitExtTable(void);
00086 static int pm_GetClientList(Display * display, Window window, Atom atom, Window ** windowList);
00087
00088 static void pm_PatchProgramTable();
00089 static void pm_UpdateXClientReference(gpointer key, gpointer value, gpointer user_data);
00090 static void pm_IconifyUserApp(gpointer key, gpointer value, gpointer user_data);
00091 static void pm_TerminateUserApp(gpointer key, gpointer value, gpointer user_data);
00092 static void pm_AddExtensionsToTable(gpointer key, gpointer value, gpointer user_data);
00093 static GString *pm_CreateCommand(char *szExec, char *szArgMask, char *filename, char *manifest, char* options);
00094
00095 static Time pm_fake_timestamp();
00096 static int pm_getWinOnTop();
00097 static void pm_setLastStartedUa(gchar * uaID);
00098
00099 void pt_key_destroy(gpointer key);
00100 void pt_value_destroy(gpointer value);
00101
00102 void et_value_destroy(gpointer value);
00103
00104
00105 static void signals_init(void);
00106 static void on_signal(int signal);
00107 static gboolean on_signal_gtk(GIOChannel* source, GIOCondition cond, gpointer p);
00108 static void on_sigchld(int signo, pid_t pid, int status);
00109
00110
00111 static void pm_DisplayXClientInfo(GArray * clientInfo);
00112
00113
00114
00115
00116
00117
00118
00119 gboolean pm_InitProgramManager(void)
00120 {
00121 gboolean returnValue = TRUE;
00122
00123 CL_PMPRINTF("entry");
00124
00125
00126 signals_init();
00127
00128 strncpy(g_uaOnTop, CONTENTLISTER_UAID, UAID_MAX_SIZE);
00129 strncpy(g_lastStartedUa, CONTENTLISTER_UAID, UAID_MAX_SIZE);
00130 g_myWin = -1;
00131 g_xClientInfo = g_array_sized_new(FALSE, TRUE, sizeof(erXClient_t), XCLIENT_ARRAY_RESERVED_SIZE);
00132
00133 returnValue = pm_InitProgramTable();
00134 if (returnValue)
00135 {
00136 pm_InitExtTable();
00137 }
00138
00139
00140 XSetErrorHandler(pm_XErrorHandler);
00141
00142 return returnValue;
00143 }
00144
00145 static int pm_XErrorHandler(Display *display, XErrorEvent *event)
00146 {
00147 char buf[1000];
00148
00149 XGetErrorText(display, event->error_code, buf, sizeof(buf));
00150 CL_ERRORPRINTF("X error: %s", buf);
00151
00152 erbusy_off();
00153
00154 return 0;
00155 }
00156
00157 void pm_SetMyWindow(Window window)
00158 {
00159 g_myWin = window;
00160 }
00161
00162 void pm_DestroyProgramManager(void)
00163 {
00164 CL_PMPRINTF("entry");
00165 signal(SIGCHLD, SIG_IGN);
00166
00167
00168
00169
00170
00171
00172 }
00173
00174 static void on_sigchld(int signo, pid_t pid, int status)
00175 {
00176 listerState_t lister_state = getListerState();
00177
00178 CL_WARNPRINTF("entry: signo [%d] pid [%d] status [0x%04X]", signo, pid, status);
00179
00180 if (pid == erConnectPid())
00181 {
00182
00183 if (WIFEXITED(status))
00184 {
00185 CL_WARNPRINTF("ConnectionMgr terminated with return value %d", WEXITSTATUS(status));
00186 }
00187 else if (WIFSIGNALED(status))
00188 {
00189 CL_WARNPRINTF("ConnectionMgr terminated by signal [%d]", WTERMSIG(status));
00190 }
00191
00192
00193 ctrl_pincode_setting_init();
00194
00195
00196 timed_ids_handle_connmgr_quit();
00197 }
00198 else
00199 {
00200
00201
00202 erApplicationInfo_t *theAppInfo = (erApplicationInfo_t *) g_hash_table_lookup(g_programInfo, g_lastStartedUa);
00203 if (theAppInfo)
00204 {
00205 CL_WARNPRINTF("last started [%s] pid [%d]", g_lastStartedUa, theAppInfo->pid);
00206
00207
00208 if (theAppInfo->pid == pid)
00209 {
00210
00211 theAppInfo->pid = -1;
00212 if (lister_state != STATE_DOWNLOADMGR)
00213 {
00214 pm_setUaOnTop(CONTENTLISTER_UAID);
00215 }
00216
00217
00218 toolbar_restore();
00219
00220
00221 if (strncmp(g_lastStartedUa, SETUP_APP, UAID_MAX_SIZE) == 0)
00222 {
00223 CL_PMPRINTF("Setup app was on top, do languagesInit() and mdsInit()");
00224
00225
00226 reload_registry();
00227
00228
00229 languagesInit();
00230 mdsInit();
00231 flipbarDirectionSettingInit();
00232 keybufferingSettingInit();
00233 ctrlSetScreenTexts();
00234 ctrl_pincode_setting_init();
00235 if (getListerState() == STATE_LANG_SEL)
00236 {
00237 CL_PMPRINTF("Exiting setup for language selection.");
00238 setListerState(STATE_NORMAL);
00239 ctrl_startup();
00240 }
00241
00242 ctrl_background_connect_timeout_start(TRUE);
00243
00244
00245 erMSDisk_handle_reread_settings();
00246
00247
00248 timed_ids_handle_reread_settings();
00249 }
00250
00251
00252 if ( lister_state != STATE_PINCODE
00253 && lister_state != STATE_DOWNLOADMGR)
00254 {
00255 erStartMSDiskApp();
00256 }
00257
00258
00259 if (getListerState() != STATE_USB_CONNECTED)
00260 {
00261 ctrl_rescan_current();
00262 }
00263 }
00264 }
00265 }
00266
00267 CL_WARNPRINTF("end");
00268 }
00269
00270 char *pm_getUaID(char *extension)
00271 {
00272 erExtInfo_t *theExtInfo = NULL;
00273
00274 CL_PMPRINTF("entry");
00275
00276 if (extension)
00277 {
00278 theExtInfo = g_hash_table_lookup(g_extensionInfo, extension);
00279
00280 if (theExtInfo)
00281 {
00282 CL_PMPRINTF("uaID %s - extension %s", (theExtInfo->uaID == NULL) ? "NULL" : theExtInfo->uaID, extension);
00283 return theExtInfo->uaID;
00284 }
00285 }
00286 return NULL;
00287 }
00288
00289 char *pm_getIcon(char *extension)
00290 {
00291 erExtInfo_t *theExtInfo = NULL;
00292
00293 if (extension)
00294 {
00295 theExtInfo = g_hash_table_lookup(g_extensionInfo, extension);
00296
00297 if (theExtInfo)
00298 {
00299 CL_PMPRINTF("iconLocation %s - extension %s",
00300 (theExtInfo->iconLocation == NULL) ? "NULL" : theExtInfo->iconLocation, extension);
00301 return theExtInfo->iconLocation;
00302 }
00303 }
00304
00305 return NULL;
00306 }
00307
00308 gboolean pm_RaiseContentLister()
00309 {
00310 Window win = 0;
00311 Display *display;
00312 int nmbrOfXClients;
00313
00314 CL_PMPRINTF("entry");
00315
00316
00317 nmbrOfXClients = pm_UpdateState();
00318 if (nmbrOfXClients < 0)
00319 {
00320 CL_ERRORPRINTF("Failed to update state");
00321 return FALSE;
00322 }
00323
00324
00325 pm_PatchProgramTable();
00326
00327
00328 win = g_myWin;
00329 display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
00330
00331 if (strcmp(pm_getUaOnTop(), CONTENTLISTER_UAID) != 0)
00332 {
00333
00334 erApplicationInfo_t *theAppInfo= (erApplicationInfo_t *)
00335 g_hash_table_lookup(g_programInfo, pm_getUaOnTop());
00336 pm_IconifyUserApp(NULL, theAppInfo, display);
00337 toolbar_restore();
00338 }
00339
00340
00341
00342 g_hash_table_foreach(g_programInfo, pm_TerminateUserApp, display);
00343
00344 XRaiseWindow(display, win);
00345 XMapRaised(display, win);
00346 XFlush(display);
00347 pm_setUaOnTop(CONTENTLISTER_UAID);
00348
00349 CL_PMPRINTF("end");
00350 return TRUE;
00351 }
00352
00353 gboolean pm_RaiseUserApp(gchar * uaId)
00354 {
00355 Window win = 0;
00356 Window CL_win = 0;
00357 Display *display;
00358 int nmbrOfXClients;
00359 int index;
00360 erApplicationInfo_t *theAppInfo;
00361 int screen;
00362 erXClient_t *client;
00363
00364 CL_PMPRINTF("entry: uaId [%s]", uaId);
00365
00366 theAppInfo = (erApplicationInfo_t *) g_hash_table_lookup(g_programInfo, uaId);
00367
00368 if (theAppInfo)
00369 {
00370
00371 nmbrOfXClients = pm_UpdateState();
00372 if (nmbrOfXClients < 0)
00373 {
00374 CL_ERRORPRINTF("Failed to update state");
00375 return FALSE;
00376 }
00377
00378
00379 pm_PatchProgramTable();
00380
00381
00382 for (index = 0; index < g_xClientInfo->len; index++)
00383 {
00384 client = &g_array_index(g_xClientInfo, erXClient_t, index);
00385
00386 if (strcmp(CONTENTLISTER_RESNAME, client->resName) == 0)
00387 {
00388 CL_win = client->win;
00389 }
00390 if (strcmp(theAppInfo->userApp->xResName, client->resName) == 0)
00391 {
00392 win = client->win;
00393 }
00394 }
00395
00396 if ((win != 0) && (CL_win != 0))
00397 {
00398 screen = gdk_x11_get_default_screen();
00399 display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
00400
00401 CL_PMPRINTF("Lower CL window");
00402 XIconifyWindow(display, CL_win, screen);
00403 XRaiseWindow(display, win);
00404 XMapRaised(display, win);
00405 XFlush(display);
00406 pm_setUaOnTop(uaId);
00407 toolbar_clear();
00408 return TRUE;
00409 }
00410 else
00411 {
00412 CL_ERRORPRINTF("could not find window info");
00413 return FALSE;
00414 }
00415 }
00416 else
00417 {
00418 CL_ERRORPRINTF("invalid uaID %s", (NULL == uaId) ? "NULL" : uaId);
00419 return FALSE;
00420 }
00421 }
00422
00423 gboolean pm_IsActive(gchar * uaId)
00424 {
00425 int nmbrOfXClients;
00426 erApplicationInfo_t *theAppInfo;
00427
00428 CL_PMPRINTF("entry %s", (uaId == NULL) ? "NULL" : uaId);
00429
00430 theAppInfo = (erApplicationInfo_t *) g_hash_table_lookup(g_programInfo, uaId);
00431
00432 if (theAppInfo)
00433 {
00434
00435 nmbrOfXClients = pm_UpdateState();
00436 if (nmbrOfXClients < 0)
00437 {
00438 CL_ERRORPRINTF("Failed to update state");
00439 return FALSE;
00440 }
00441
00442
00443 pm_PatchProgramTable();
00444
00445 if (NULL != theAppInfo->xclient)
00446 {
00447 return TRUE;
00448 }
00449 else
00450 {
00451 return FALSE;
00452 }
00453 }
00454 else
00455 {
00456 CL_ERRORPRINTF("invalid uaID %s", (NULL == uaId) ? "NULL" : uaId);
00457 return FALSE;
00458 }
00459 }
00460
00461 void pm_SendKey(KeySym keysym)
00462 {
00463 XKeyEvent xev;
00464 Display *display;
00465 Window window, root;
00466 int screen;
00467
00468 display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
00469 root = gdk_x11_get_default_root_xwindow();
00470 window = pm_getWinOnTop();
00471 if (window == -1)
00472 {
00473 CL_ERRORPRINTF("Failed: no valid window found");
00474 return;
00475 }
00476
00477 if (window == g_myWin)
00478 {
00479 CL_PMPRINTF("ContentLister window 0x%x", (unsigned int)window);
00480
00481 display = XOpenDisplay(NULL);
00482 screen = DefaultScreen(display);
00483 root = RootWindow(display, screen);
00484 }
00485
00486
00487 xev.type = KeyPress;
00488 xev.display = display;
00489 xev.root = root;
00490 xev.window = window;
00491 xev.subwindow = None;
00492 xev.time = pm_fake_timestamp();
00493 xev.x = 1;
00494 xev.y = 1;
00495 xev.x_root = 1;
00496 xev.y_root = 1;
00497 xev.same_screen = 1;
00498 xev.state = 0;
00499 xev.keycode = XKeysymToKeycode(display, keysym);
00500
00501 XSendEvent(xev.display, window, 1, KeyPressMask, (XEvent *) & xev);
00502
00503
00504
00505
00506 if ( keysym == GDK_F5 )
00507 {
00508 CL_ERRORPRINTF("NOT Sending keyrelease for UP key....");
00509 }
00510 else
00511 {
00512
00513 xev.type = KeyRelease;
00514 xev.time = pm_fake_timestamp();
00515 XSendEvent(xev.display, window, 1, KeyReleaseMask, (XEvent *) & xev);
00516 }
00517
00518
00519 XSync(xev.display, FALSE);
00520
00521 if (window == g_myWin)
00522 {
00523 CL_PMPRINTF("Before XCloseDisplay()");
00524 XCloseDisplay(display);
00525 }
00526 }
00527
00528 gchar *pm_getUaOnTop()
00529 {
00530 CL_PMPRINTF("return UaID [%s]", g_uaOnTop);
00531 return g_uaOnTop;
00532 }
00533
00534 static Time pm_fake_timestamp()
00535 {
00536 int tint;
00537 struct timeval tv;
00538
00539 gettimeofday(&tv, NULL);
00540 tint = (int) tv.tv_sec * 1000;
00541 tint = tint / 1000 * 1000;
00542 tint = tint + tv.tv_usec / 1000;
00543 return (Time) tint;
00544 }
00545
00546
00547 static void pm_IconifyUserApp(gpointer key, gpointer value, gpointer user_data)
00548 {
00549 erApplicationInfo_t *theAppInfo = (erApplicationInfo_t *) value;
00550 Display *display = (Display *) user_data;
00551
00552 CL_PMPRINTF("entry");
00553
00554 if ((theAppInfo) && (user_data))
00555 {
00556 int screen = gdk_x11_get_default_screen();
00557
00558 if (theAppInfo->xclient != NULL)
00559 {
00560 CL_PMPRINTF("Lower window %s", theAppInfo->userApp->xResName);
00561 XIconifyWindow(display, theAppInfo->xclient->win, screen);
00562 }
00563 }
00564 }
00565
00566
00567 static void pm_TerminateUserApp(gpointer key, gpointer value, gpointer user_data)
00568 {
00569 int i;
00570 pid_t pid;
00571 erApplicationInfo_t *theAppInfo = (erApplicationInfo_t *) value;
00572
00573 CL_PMPRINTF("entry: xResName [%s]", theAppInfo->userApp->xResName);
00574
00575 if ((theAppInfo) && (user_data))
00576 {
00577 if (theAppInfo->pid != -1)
00578 {
00579
00580 pid = theAppInfo->pid;
00581 CL_WARNPRINTF("Terminate process [%s] pid [%d]", theAppInfo->userApp->xResName, pid);
00582 kill(pid, SIGTERM);
00583
00584
00585 i = 300;
00586 while (kill(pid, 0) == 0 && i > 0)
00587 {
00588
00589 usleep(100*1000);
00590 i--;
00591 }
00592
00593 if (i == 0)
00594 {
00595
00596 kill(pid, SIGKILL);
00597 i = 100;
00598 while (kill(pid, 0) == 0 && i > 0)
00599 {
00600
00601 usleep(100*1000);
00602 i--;
00603 }
00604
00605 if (i == 0)
00606 {
00607
00608 theAppInfo->pid = -1;
00609 }
00610 }
00611 }
00612 }
00613 CL_PMPRINTF("end");
00614 }
00615
00616 void pm_setUaOnTop(gchar * uaID)
00617 {
00618 CL_PMPRINTF("entry: uaID [%s]", uaID);
00619 strncpy(g_uaOnTop, uaID, UAID_MAX_SIZE);
00620 }
00621
00622 void pm_setLastStartedUa(gchar * uaID)
00623 {
00624 CL_PMPRINTF("entry: uaID [%s]", uaID);
00625 strncpy(g_lastStartedUa, uaID, UAID_MAX_SIZE);
00626 }
00627
00628
00629
00630 static int pm_getWinOnTop()
00631 {
00632 int nmbrOfXClients;
00633 char *uaId;
00634 Window win = -1;
00635 erApplicationInfo_t *theAppInfo;
00636
00637 CL_PMPRINTF("entry");
00638
00639 uaId = pm_getUaOnTop();
00640
00641 if (strncmp(uaId, CONTENTLISTER_UAID, UAID_MAX_SIZE) == 0)
00642 {
00643
00644 win = g_myWin;
00645 }
00646 else
00647 {
00648
00649 nmbrOfXClients = pm_UpdateState();
00650 if (nmbrOfXClients < 0)
00651 {
00652 CL_ERRORPRINTF("Failed to update state");
00653 }
00654 else
00655 {
00656
00657 pm_PatchProgramTable();
00658
00659 theAppInfo = (erApplicationInfo_t *) g_hash_table_lookup(g_programInfo, uaId);
00660 if (theAppInfo != NULL && theAppInfo->xclient != NULL)
00661 {
00662
00663 win = theAppInfo->xclient->win;
00664 CL_PMPRINTF("window with id (0x%x)", (unsigned int)win);
00665 }
00666 else
00667 {
00668
00669 CL_ERRORPRINTF("theAppInfo [%p]", theAppInfo);
00670 if (theAppInfo)
00671 {
00672 CL_ERRORPRINTF("theAppInfo->xclient [%p]", theAppInfo->xclient);
00673 }
00674 return -1;
00675 }
00676 }
00677 }
00678 return win;
00679 }
00680
00681 int pm_RunViewer(gchar * uaID, char *filename, char *manifest, char *options, int reuse)
00682 {
00683 pid_t pid;
00684 int nmbrOfXClients;
00685 erApplicationInfo_t *theAppInfo;
00686 Display *display;
00687 Window ownWin = 0;
00688 int index;
00689 erXClient_t *client;
00690 int screen;
00691 GString *theCommand;
00692
00693 theAppInfo = (erApplicationInfo_t *) g_hash_table_lookup(g_programInfo, (const char*)uaID);
00694
00695 if (theAppInfo)
00696 {
00697 CL_PMPRINTF("App %s", theAppInfo->uaID);
00698
00699 toolbar_clear();
00700
00701
00702 nmbrOfXClients = pm_UpdateState();
00703 if (nmbrOfXClients < 0)
00704 {
00705 CL_ERRORPRINTF("Failed to update state");
00706 return (ERR_STATE_UPDATE);
00707 }
00708
00709
00710 pm_PatchProgramTable();
00711
00712 if (reuse == 1)
00713 {
00714 CL_PMPRINTF("Re-use process branch");
00715
00716
00717 if (theAppInfo->pid != -1)
00718 {
00719
00720
00721 CL_WARNPRINTF("TODO: Bring %s on top of window stack", uaID);
00722
00723 if (theAppInfo->xclient != NULL)
00724 {
00725 CL_PMPRINTF("Do something with %s 0x%xd",
00726 theAppInfo->xclient->resName,
00727 (unsigned int)theAppInfo->xclient->win);
00728
00729 CL_PMPRINTF("XRaiseWindow: 0x%x (window)", (unsigned int)theAppInfo->xclient->win);
00730
00731 display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
00732
00733
00734 for (index = 0; index < g_xClientInfo->len; index++)
00735 {
00736 client = &g_array_index(g_xClientInfo, erXClient_t, index);
00737
00738 if (strcmp(CONTENTLISTER_RESNAME, client->resName) == 0)
00739 {
00740 ownWin = client->win;
00741 break;
00742 }
00743 }
00744
00745 if (ownWin != 0)
00746 {
00747 screen = gdk_x11_get_default_screen();
00748
00749 CL_PMPRINTF("Lower window %s", client->resName);
00750 XIconifyWindow(display, ownWin, screen);
00751 }
00752
00753 XMapRaised(display, theAppInfo->xclient->win);
00754 XRaiseWindow(display, theAppInfo->xclient->win);
00755 XFlush(display);
00756 pm_setUaOnTop(uaID);
00757
00758
00759 return (ERR_OK);
00760 }
00761 else
00762 {
00763 CL_ERRORPRINTF("Did not find xclient info on %s. Should I kill the process here????", uaID);
00764 }
00765 }
00766
00767 }
00768 else
00769 {
00770 CL_PMPRINTF("Create new process branch");
00771
00772
00773 if (theAppInfo->pid != -1)
00774 {
00775 CL_WARNPRINTF("Process was already started, not starting it again!");
00776 return (ERR_VIEWER_RUNNING);
00777 }
00778
00779 }
00780
00781
00782 theCommand = pm_CreateCommand(theAppInfo->userApp->szExec, theAppInfo->userApp->szArgMask, filename, manifest, options);
00783
00784 if (theCommand)
00785 {
00786 CL_PMPRINTF("szCommand %s", theCommand->str);
00787 }
00788 else
00789 {
00790 CL_ERRORPRINTF("pm_CreateArgument can't create command");
00791 return (ERR_ARGUMENT);
00792 }
00793
00794
00795 if (strcmp(uaID, ARINC_APP) == 0)
00796 {
00797
00798
00799
00800
00801 char *p = realpath(theAppInfo->userApp->szExec, NULL);
00802 if (p == NULL)
00803 {
00804 CL_WARNPRINTF("Cannot find executable [%s]; not executing in place.", theAppInfo->userApp->szExec);
00805 return (ERR_FORK);
00806 }
00807 else
00808 {
00809 g_free(p);
00810 int nRet;
00811 CL_WARNPRINTF("Executing [%s] in place; replaces contentLister!", uaID);
00812 nRet = shell_exec(theCommand->str);
00813 CL_ERRORPRINTF("shell_exec of [%s] failed!", uaID);
00814 CL_ERRORPRINTF("shell exec command [%s]", theCommand->str);
00815 CL_ERRORPRINTF("shell_exec returned %d", nRet);
00816 perror("Error upon calling shell_exec");
00817 fflush(stderr);
00818 return (ERR_FORK);
00819 }
00820 }
00821 else
00822 {
00823 erStopMSDiskApp();
00824
00825 switch (pid = fork())
00826 {
00827 case 0:
00828 {
00829
00830 int nRet;
00831
00832 nRet = shell_exec(theCommand->str);
00833 CL_ERRORPRINTF("shell_exec of [%s] failed, cleaning up child", uaID);
00834 CL_ERRORPRINTF("shell exec command [%s]", theCommand->str);
00835 CL_ERRORPRINTF("shell_exec returned %d", nRet);
00836 perror("Error upon calling shell_exec");
00837 fflush(stderr);
00838 sleep(1);
00839 _exit(1);
00840 }
00841 case -1:
00842
00843 CL_ERRORPRINTF("pmRunViewer: can't fork %s", uaID);
00844 g_string_free(theCommand, TRUE);
00845 erStartMSDiskApp();
00846 return (ERR_FORK);
00847 }
00848 }
00849
00850
00851
00852 theAppInfo->pid = pid;
00853 pm_setUaOnTop(uaID);
00854 pm_setLastStartedUa(uaID);
00855 g_string_free(theCommand, TRUE);
00856 return (ERR_OK);
00857 }
00858 else
00859 {
00860 CL_WARNPRINTF("invalid uaID %s", (NULL == uaID) ? "NULL" : uaID);
00861 return (ERR_INVALID_UAID);
00862 }
00863
00864 }
00865
00866 static GString *pm_CreateCommand(char *szExec, char *szArgMask, char *filename, char *manifest, char *options)
00867 {
00868 GString *theCommand = NULL;
00869 char *file_ptr;
00870 char *manifest_ptr;
00871 int location = 0;
00872
00873 if ((szExec) && (szArgMask))
00874 {
00875 theCommand = g_string_sized_new(COMMAND_MAX_SIZE);
00876
00877 if (theCommand)
00878 {
00879 g_string_printf(theCommand, "%s", szExec);
00880 g_string_append_printf(theCommand, " ");
00881 g_string_append_printf(theCommand, "%s", szArgMask);
00882
00883 CL_PMPRINTF("theCommand %s", theCommand->str);
00884
00885 file_ptr = g_strstr_len(theCommand->str, theCommand->len, FILENAME_ARG);
00886
00887 if (file_ptr && filename)
00888 {
00889 location = file_ptr - theCommand->str;
00890
00891 CL_PMPRINTF("%s location %d", FILENAME_ARG, location);
00892
00893 g_string_erase(theCommand, location, strlen(FILENAME_ARG));
00894 g_string_insert(theCommand, location, "\"\"");
00895 g_string_insert(theCommand, location + 1, filename);
00896
00897 CL_PMPRINTF("inserted filename => %s", theCommand->str);
00898 }
00899 else
00900 {
00901 CL_PMPRINTF("file_ptr %s - filename %s", (file_ptr == NULL) ? "NULL" : file_ptr,
00902 (filename == NULL) ? "NULL" : filename);
00903 }
00904
00905 manifest_ptr = g_strstr_len(theCommand->str, theCommand->len, MANIFEST_ARG);
00906 if (manifest_ptr && manifest)
00907 {
00908 location = manifest_ptr - theCommand->str;
00909
00910 CL_PMPRINTF("%s location %d", MANIFEST_ARG, location);
00911
00912 g_string_erase(theCommand, location, strlen(FILENAME_ARG));
00913 g_string_insert(theCommand, location, "\"\"");
00914 g_string_insert(theCommand, location + 1, manifest);
00915
00916 CL_PMPRINTF("inserted manifest => %s", theCommand->str);
00917 }
00918 else
00919 {
00920 CL_PMPRINTF("manifest_ptr %s - manifest %s", (manifest_ptr == NULL) ? "NULL" : manifest_ptr,
00921 (filename == NULL) ? "NULL" : manifest);
00922 }
00923
00924 if (options)
00925 {
00926 g_string_append_printf(theCommand, " ");
00927 g_string_append_printf(theCommand, "%s", options);
00928 CL_PMPRINTF("inserted extra options => %s", theCommand->str);
00929 }
00930 }
00931 }
00932 return theCommand;
00933 }
00934
00935
00936
00937
00938 static int pm_UpdateState()
00939 {
00940 Display *display;
00941 Window rootWindow;
00942 Atom net_client_list;
00943 int nWindows;
00944 Window *windowList;
00945 int i;
00946 erXClient_t xClient;
00947
00948 GArray *clientInfo = g_xClientInfo;
00949
00950 CL_PMPRINTF("entry");
00951
00952 display = gdk_x11_display_get_xdisplay(gdk_display_get_default());
00953 XSync(display, FALSE);
00954
00955 net_client_list = XInternAtom(display, "_NET_CLIENT_LIST", False);
00956 rootWindow = gdk_x11_get_default_root_xwindow();
00957 nWindows = pm_GetClientList(display, rootWindow, net_client_list, &windowList);
00958 if (nWindows < 0)
00959 {
00960 CL_ERRORPRINTF("Failed to retrieve the number of clients");
00961 return -1;
00962 }
00963
00964
00965 if (clientInfo->len > 0)
00966 {
00967 clientInfo = g_array_remove_range(clientInfo, 0, clientInfo->len);
00968 }
00969
00970 for (i = 0; i < nWindows; i++)
00971 {
00972 XClassHint classHints;
00973
00974 CL_PMPRINTF("windowList[%d]: 0x%lx", i, windowList[i]);
00975
00976 memset(&xClient, 0, sizeof(erXClient_t));
00977
00978
00979 xClient.win = windowList[i];
00980
00981
00982 if (XGetClassHint(display, windowList[i], &classHints))
00983 {
00984 CL_PMPRINTF("Res Name: %s - Res Class: %s.", classHints.res_name, classHints.res_class);
00985 strncpy(xClient.resName, classHints.res_name, WM_NAME_MAX - 1);
00986 XFree(classHints.res_name);
00987 XFree(classHints.res_class);
00988 }
00989 else
00990 {
00991 CL_ERRORPRINTF("Failed to fetch class hint for window 0x%lx", windowList[i]);
00992 }
00993
00994
00995
00996
00997
00998 g_array_append_val(clientInfo, xClient);
00999 }
01000
01001
01002
01003 g_xClientInfo = clientInfo;
01004
01005
01006 XFree(windowList);
01007 return nWindows;
01008 }
01009
01010
01011 static void pm_DisplayXClientInfo(GArray * clientInfo)
01012 {
01013 int index;
01014 erXClient_t *client;
01015
01016 CL_PMPRINTF("entry");
01017
01018 for (index = 0; index < clientInfo->len; index++)
01019 {
01020 client = &g_array_index(clientInfo, erXClient_t, index);
01021
01022 CL_PMPRINTF("");
01023 CL_PMPRINTF("clientInfo[%d] address 0x%x", index, (unsigned int)client);
01024 CL_PMPRINTF("resName %s", client->resName);
01025 CL_PMPRINTF("window id 0x%x", (unsigned int)client->win);
01026
01027 }
01028 }
01029
01030
01031 static int pm_GetClientList(Display * display, Window window, Atom atom, Window ** windowList)
01032 {
01033 unsigned char *data;
01034 int real_format;
01035 Atom real_type;
01036 unsigned long itemsRead, itemsLeft;
01037
01038 CL_PMPRINTF("entry");
01039
01040 if (XGetWindowProperty(display, window, atom, 0, 0x7fffffff,
01041 False, XA_WINDOW, &real_type, &real_format, &itemsRead, &itemsLeft,
01042 (unsigned char **) &data) == Success && itemsRead >= 1)
01043 {
01044
01045 CL_PMPRINTF("%ld top level windows", itemsRead);
01046 *windowList = (Window *) data;
01047 return itemsRead;
01048 }
01049 return -1;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059 static gboolean pm_InitProgramTable(void)
01060 {
01061 gboolean returnValue = TRUE;
01062 regUserApp_t *theUserApp = NULL;
01063 regUserAppList_t *theUserAppList = NULL;
01064 erApplicationInfo_t *theApplicationInfo = NULL;
01065 char *key = NULL;
01066 int i;
01067 struct stat file_stat;
01068
01069 CL_PMPRINTF("entry");
01070
01071 theUserAppList = erRegGetUserAppList();
01072 if (theUserAppList)
01073 {
01074 CL_PMPRINTF("erRegReadUserAppList returned %d values", theUserAppList->uaIDArraySize);
01075 g_programInfo = g_hash_table_new_full(g_str_hash, g_str_equal, pt_key_destroy, pt_value_destroy);
01076 for (i = 0; i < theUserAppList->uaIDArraySize; i++)
01077 {
01078 theUserApp = erRegGetUserApp(theUserAppList->uaIDArray[i]);
01079 if (theUserApp)
01080 {
01081 theApplicationInfo = g_new0(erApplicationInfo_t, 1);
01082
01083 theApplicationInfo->userApp = theUserApp;
01084 strncpy(theApplicationInfo->uaID, theUserAppList->uaIDArray[i], UAID_MAX_SIZE);
01085 theApplicationInfo->pid = -1;
01086
01087
01088 if (stat(theApplicationInfo->userApp->szExec, &file_stat) == 0)
01089 {
01090 theApplicationInfo->enabled = TRUE;
01091 }
01092 else
01093 {
01094 CL_WARNPRINTF("Application [%s] executable [%s] is not found: disabled it", theApplicationInfo->uaID, theApplicationInfo->userApp->szExec);
01095 theApplicationInfo->enabled = FALSE;
01096 }
01097
01098 CL_PMPRINTF("g_hash_table_insert %s", theUserAppList->uaIDArray[i]);
01099
01100 key = g_strdup(theUserAppList->uaIDArray[i]);
01101
01102 g_hash_table_insert(g_programInfo, key, theApplicationInfo);
01103 }
01104 }
01105 erRegFreeUserAppList(theUserAppList);
01106
01107 }
01108 else
01109 {
01110 CL_ERRORPRINTF("erRegReadUserAppList returned NULL");
01111 returnValue = FALSE;
01112 }
01113
01114 return returnValue;
01115 }
01116
01117
01118 static void pm_InitExtTable(void)
01119 {
01120 CL_PMPRINTF("entry");
01121
01122 g_extensionInfo = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, et_value_destroy);
01123
01125 regExtInfoList_t *theRegExtInfoList = 0;
01126 theRegExtInfoList = erRegGetExtInfoList(NULL);
01127 if (theRegExtInfoList)
01128 {
01129 g_hash_table_foreach(g_programInfo, pm_AddExtensionsToTable, theRegExtInfoList);
01130 erRegFreeExtInfoList(theRegExtInfoList);
01131 }
01132 else
01133 {
01134 CL_ERRORPRINTF("erRegGetExtInfoList returns NULL");
01135 }
01136
01137 }
01138
01139 static void pm_AddExtensionsToTable(gpointer key, gpointer value, gpointer user_data)
01140 {
01141 int index;
01142 erApplicationInfo_t *theApplicationInfo = (erApplicationInfo_t *) value;
01143 regExtInfoList_t *theRegExtInfoList = (regExtInfoList_t *) user_data;
01144 erExtInfo_t *theExtInfo;
01145
01146
01147 if ((theApplicationInfo) && (theRegExtInfoList) && (theApplicationInfo->enabled))
01148 {
01149
01150
01151
01152 for (index = 0; index < theApplicationInfo->userApp->extensionArraySize; index++)
01153 {
01154 theExtInfo = g_new0(erExtInfo_t, 1);
01155
01156 if (theRegExtInfoList)
01157 {
01158
01159
01160 int i = 0, order = INT_MAX, pos = -1;
01161 for(; i < theRegExtInfoList->extArraySize; ++i)
01162 {
01163
01164 if ((theRegExtInfoList->extArray[i].extName) &&
01165 (strcmp(theApplicationInfo->userApp->extensionArray[index],
01166 theRegExtInfoList->extArray[i].extName) == 0))
01167 {
01168 if (order > theRegExtInfoList->extArray[i].associateOrder)
01169 {
01170 order = theRegExtInfoList->extArray[i].associateOrder;
01171 pos = i;
01172 }
01173 }
01174 }
01175
01176 if (pos != -1)
01177 {
01178 theExtInfo->uaID = g_strdup(theRegExtInfoList->extArray[pos].associateApp);
01179 theExtInfo->iconLocation = g_strdup(theRegExtInfoList->extArray[pos].iconLocation);
01180 }
01181 else
01182 {
01183 CL_WARNPRINTF("Program %s associated with [%s] without extensionInfo entry in registry. Consider fixing this!",
01184 theApplicationInfo->uaID, theApplicationInfo->userApp->extensionArray[index]);
01185 theExtInfo->uaID = theApplicationInfo->uaID;
01186 theExtInfo->iconLocation = NULL;
01187 }
01188 }
01189 else
01190 {
01191 theExtInfo->uaID = theApplicationInfo->uaID;
01192 }
01193
01194 CL_PMPRINTF("add %s - %s - %s", theApplicationInfo->userApp->extensionArray[index],
01195 theApplicationInfo->uaID,
01196 (theExtInfo->iconLocation == NULL) ? "NULL" : theExtInfo->iconLocation);
01197
01198 g_hash_table_insert(g_extensionInfo, theApplicationInfo->userApp->extensionArray[index], theExtInfo);
01199 }
01200 }
01201 }
01202
01203
01204 void pt_key_destroy(gpointer key)
01205 {
01206 if (key)
01207 {
01208 CL_PMPRINTF("%s", (char*)key);
01209 g_free(key);
01210 key = NULL;
01211 }
01212 }
01213
01214
01215
01216
01217 void pt_value_destroy(gpointer value)
01218 {
01219 erApplicationInfo_t *theApplicationInfo = (erApplicationInfo_t*)value;
01220
01221 if (theApplicationInfo)
01222 {
01223 CL_PMPRINTF("%s", theApplicationInfo->uaID);
01224
01225 if (theApplicationInfo->userApp)
01226 {
01227 erRegFreeUserApp(theApplicationInfo->userApp);
01228 }
01229
01230 g_free(theApplicationInfo);
01231 theApplicationInfo = NULL;
01232 }
01233 }
01234
01235
01236
01237 void et_value_destroy(gpointer value)
01238 {
01239 erExtInfo_t *theExtInfo;
01240
01241 if (value)
01242 {
01243 theExtInfo = (erExtInfo_t *) value;
01244
01245 CL_PMPRINTF("%s", theExtInfo->uaID);
01246
01247 if (theExtInfo->iconLocation)
01248 {
01249 g_free(theExtInfo->iconLocation);
01250 }
01251
01252 g_free(theExtInfo);
01253 theExtInfo = NULL;
01254 }
01255 }
01256
01257 static void pm_PatchProgramTable()
01258 {
01259 pm_DisplayXClientInfo(g_xClientInfo);
01260 g_hash_table_foreach(g_programInfo, pm_UpdateXClientReference, g_xClientInfo);
01261 }
01262
01263 static void pm_UpdateXClientReference(gpointer key, gpointer value, gpointer user_data)
01264 {
01265 int index;
01266 erXClient_t *client;
01267 erApplicationInfo_t *theApplicationInfo = (erApplicationInfo_t *) value;
01268 GArray *clientInfo = (GArray *) user_data;
01269
01270 CL_PMPRINTF("entry");
01271
01272 if ((g_xClientInfo) && (theApplicationInfo))
01273 {
01274
01275 theApplicationInfo->xclient = NULL;
01276 CL_PMPRINTF("App %s", theApplicationInfo->uaID);
01277
01278 for (index = 0; index < g_xClientInfo->len; index++)
01279 {
01280 client = &g_array_index(clientInfo, erXClient_t, index);
01281
01282 if (strcmp(theApplicationInfo->userApp->xResName, client->resName) == 0)
01283 {
01284 CL_PMPRINTF("Updating [%s] with resname [%s] to windowid [0x%x]",
01285 theApplicationInfo->uaID,
01286 client->resName,
01287 (unsigned int)client->win);
01288 theApplicationInfo->xclient = client;
01289 break;
01290 }
01291 }
01292 }
01293 else
01294 {
01295 CL_ERRORPRINTF("g_xClientInfo or theApplicationInfo is NULL");
01296 }
01297 }
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308 #define PIPE_READ 0
01309 #define PIPE_WRITE 1
01310
01311 static int signal_pipe[2];
01312
01313 typedef struct
01314 {
01315 int signo;
01316 pid_t pid;
01317 int status;
01318 } signal_data_t;
01319
01320
01321 static void signals_init()
01322 {
01323 CL_LOGPRINTF("entry");
01324
01325 int i;
01326 long fd_flags;
01327 GIOFlags io_flags;
01328 GIOChannel* io_channel = NULL;
01329 GError* error = NULL;
01330
01331
01332 i = pipe(signal_pipe);
01333 g_assert(i == 0);
01334
01335
01336 fd_flags = fcntl(signal_pipe[PIPE_WRITE], F_GETFL);
01337 g_assert(fd_flags != -1);
01338 i = fcntl(signal_pipe[PIPE_WRITE], F_SETFL, fd_flags | O_NONBLOCK);
01339 g_assert(i == 0);
01340
01341
01342 io_channel = g_io_channel_unix_new(signal_pipe[PIPE_READ]);
01343
01344
01345 g_io_channel_set_encoding(io_channel, NULL, &error);
01346 g_assert(error == NULL);
01347
01348
01349 io_flags = g_io_channel_get_flags(io_channel);
01350 g_io_channel_set_flags(io_channel, io_flags | G_IO_FLAG_NONBLOCK, &error);
01351 g_assert(error == NULL);
01352
01353
01354 g_io_add_watch(io_channel, G_IO_IN | G_IO_PRI, on_signal_gtk, NULL);
01355
01356
01357 struct sigaction on_chld;
01358 memset(&on_chld, 0x00, sizeof(on_chld));
01359 on_chld.sa_handler = on_signal;
01360 on_chld.sa_flags = SA_NOCLDSTOP;
01361 sigaction(SIGCHLD, &on_chld, NULL);
01362 }
01363
01364
01365 static void on_signal(int signal)
01366 {
01367 int bytes_written;
01368 int status;
01369 signal_data_t data;
01370 pid_t pid;
01371 gboolean done;
01372 gboolean do_write;
01373
01374 CL_LOGPRINTF("entry: signal [%d]", signal);
01375
01376 done = FALSE;
01377 data.signo = signal;
01378 data.pid = 0;
01379 data.status = 0;
01380 while (!done)
01381 {
01382 do_write = FALSE;
01383 if (signal == SIGCHLD)
01384 {
01385
01386
01387
01388 pid = waitpid(-1, &status, WNOHANG);
01389 if (pid > 0)
01390 {
01391 CL_PMPRINTF("child died: pid [%d] exited [%d] signaled [%d]",
01392 pid, WIFEXITED(status), WIFSIGNALED(status) );
01393
01394
01395 if ( WIFEXITED(status) || WIFSIGNALED(status) )
01396 {
01397
01398 data.pid = pid;
01399 data.status = status;
01400 do_write = TRUE;
01401
01402
01403
01404 button_block_all_keys(TRUE);
01405 }
01406 }
01407 else
01408 {
01409
01410 done = TRUE;
01411 }
01412 }
01413 else
01414 {
01415
01416 done = TRUE;
01417 }
01418
01419 if (do_write)
01420 {
01421 bytes_written = write(signal_pipe[PIPE_WRITE], &data, sizeof(data));
01422 fsync(signal_pipe[PIPE_WRITE]);
01423 if (bytes_written != sizeof(data))
01424 {
01425 CL_ERRORPRINTF("unix signal [%d] [%d] lost\n", data.signo, data.pid);
01426 }
01427 }
01428 }
01429 }
01430
01431
01432 static gboolean on_signal_gtk(GIOChannel* source, GIOCondition cond, gpointer p)
01433 {
01434 CL_LOGPRINTF("entry");
01435
01436 signal_data_t data;
01437 GIOStatus status;
01438 gsize bytes_read;
01439 gboolean done;
01440 GError* error = NULL;
01441
01442
01443
01444
01445 done = FALSE;
01446 while (done == FALSE)
01447 {
01448 status = g_io_channel_read_chars(source, (char*)&data, sizeof(data), &bytes_read, &error);
01449 if (status == G_IO_STATUS_NORMAL)
01450 {
01451 g_assert(error == NULL);
01452
01453 if (bytes_read == sizeof(data))
01454 {
01455
01456 CL_LOGPRINTF("signal read from pipe: [%d] [%d] [%d]", data.signo, data.pid, data.status);
01457 if (data.signo == SIGCHLD)
01458 {
01459 CL_LOGPRINTF("read a SIGCHLD signal");
01460 on_sigchld(data.signo, data.pid, data.status);
01461
01462
01463
01464
01465 if (get_timedids_connect_reason() != connect_after_wakeup)
01466 {
01467 button_block_all_keys(FALSE);
01468 }
01469 }
01470 else
01471 {
01472 CL_ERRORPRINTF("Unexpected signal [%d] [%d]", data.signo, data.pid);
01473 }
01474 }
01475 else
01476 {
01477
01478 CL_ERRORPRINTF("incomplete read from pipe: requested [%d] received [%d]", sizeof(data), bytes_read);
01479 done = TRUE;
01480 }
01481 }
01482 else if (status == G_IO_STATUS_AGAIN)
01483 {
01484
01485 CL_LOGPRINTF("pipe empty");
01486 done = TRUE;
01487 }
01488 else
01489 {
01490 CL_ERRORPRINTF("unexpected return g_io_channel_read_chars [%d]", status);
01491 done = TRUE;
01492 }
01493 }
01494
01495 return (TRUE);
01496 }
01497
01498
01500
01501
01502
01503
01504
01505
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571
01572
01573
01574
01575
01576
01577
01578
01579
01580
01581
01582
01583
01584
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598