00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <glib.h>
00033 #include <hal/libhal.h>
00034 #include <stdio.h>
00035 #include <signal.h>
00036 #include <string.h>
00037
00038
00039
00040
00041 #include "log.h"
00042 #include "busy.h"
00043 #include "devicelist.h"
00044 #include "hal.h"
00045 #include "ipc.h"
00046 #include "process.h"
00047 #include "system.h"
00048 #include "tasks.h"
00049 #include "xwindow.h"
00050
00051
00052
00053
00054
00055
00056 typedef struct
00057 {
00058 proc_t *proc;
00059 Window window;
00060 gchar *application;
00061 gchar *document;
00062 gchar *label;
00063 gchar *image;
00064 } task_t;
00065
00066 typedef struct
00067 {
00068 task_t *task;
00069 eripc_context_t *context;
00070 gchar *message_id;
00071 } request_t;
00072
00073
00074
00075
00076
00077
00078
00079 static const gint TIMEOUT_CHILD_NEW = 30;
00080 static const gint TIMEOUT_CHILD_CLOSE = 5;
00081 static const gint TIMEOUT_CHECK_RESTART_UDS = 5;
00082
00083 static const gint TIMER_CHECK_WINDOW_MS = 500;
00084 static const guint MAX_TASKS = 4;
00085
00086
00087
00088
00089
00090
00091 #define FOLDER_XID -1
00092
00093 static GSList *g_tasklist = NULL;
00094 static gboolean g_forced_close = FALSE;
00095 static gint g_child_terminate_source = 0;
00096 static gint g_check_child_window_source = 0;
00097 static gint g_task_pending_source = 0;
00098
00099
00100
00101
00102
00103
00104 static gboolean child_new (const char *command,
00105 const char *working_dir,
00106 const char *application,
00107 const char *document,
00108 const char *label,
00109 const char *image,
00110 eripc_context_t *context,
00111 const char *message_id);
00112
00113 static gboolean child_activate (task_t *task);
00114 static gboolean child_close (task_t *task);
00115
00116 static gboolean child_window_open (task_t *task, request_t *request);
00117 static gboolean child_window_close (task_t *task, request_t *request);
00118
00119 static void on_window_open_callback (eripc_context_t *context,
00120 const eripc_event_info_t *info,
00121 request_t *request);
00122
00123 static void on_window_close_callback(eripc_context_t *context,
00124 const eripc_event_info_t *info,
00125 request_t *request);
00126
00127 static gboolean on_check_child_window (gpointer data);
00128 static gboolean on_child_new_timeout (gpointer data);
00129 static gboolean on_child_term_timeout (gpointer data);
00130
00131
00132
00133
00134
00135
00136 static task_t *tasklist_add (proc_t *proc,
00137 const char *application,
00138 const char *document,
00139 const char *label,
00140 const char *image,
00141 Window window);
00142
00143 static gboolean tasklist_set_first (task_t *task);
00144 static gboolean tasklist_remove_pid (GPid pid);
00145 static gboolean tasklist_remove_window (Window window);
00146 static task_t *find_valid_task (task_t *task);
00147 static void free_task (task_t *task);
00148
00149 static task_t *get_task (const char *application, const char *document);
00150 static task_t *get_task_by_xid (Window xid);
00151
00152 static gboolean parse_commandline (const gchar *command_line,
00153 gchar **application,
00154 gchar **document,
00155 gchar **arguments);
00156
00157 static request_t *new_request (task_t *task,
00158 eripc_context_t *context,
00159 const char *message_id);
00160
00161 static void free_request (request_t *request);
00162
00163
00164
00165
00166
00167
00168 gboolean task_start(const char *command_line,
00169 const char *working_dir,
00170 const char *label,
00171 const char *image,
00172 eripc_context_t *context,
00173 const char *message_id)
00174 {
00175 LOGPRINTF("entry: `%s`", command_line);
00176
00177 gboolean retval = FALSE;
00178 gchar *application = NULL;
00179 gchar *document = NULL;
00180
00181 parse_commandline(command_line, &application, &document, NULL);
00182
00183 LOGPRINTF("app [%s] wd [%s] doc [%s] label [%s] image [%s]", application, working_dir, document, label, image);
00184
00185 task_t *task = get_task(application, document);
00186 if (task)
00187 {
00188 LOGPRINTF("task exists, reopen or activate");
00189
00190
00191 if (task->proc && task->proc->ipc_service && task->proc->is_multidoc)
00192 {
00193 request_t *request = new_request(task, context, message_id);
00194 retval = child_window_open(task, request);
00195 }
00196 else
00197 {
00198 retval = child_activate(task);
00199 if (context && message_id)
00200 {
00201
00202 ipc_send_reply_task_start(context, message_id, 0, NULL);
00203 }
00204 }
00205 }
00206 else
00207 {
00208 proc_t *proc = process_get_by_name(application);
00209 if (proc)
00210 {
00211
00212
00213 if (proc->ipc_service && proc->is_multidoc)
00214 {
00215 LOGPRINTF("task %s, %s not found, create it...", application, document);
00216 task_t *task = tasklist_add(proc, application, document, label, image, 0);
00217 request_t *request = new_request(task, context, message_id);
00218 retval = child_window_open(task, request);
00219 }
00220 else
00221 {
00222 if (proc->is_multidoc) {
00223 LOGPRINTF("%s, %s is currently running but is not a task, ignored.", application, document);
00224
00225
00226
00227 } else {
00228
00229
00230 LOGPRINTF("process %s running, but not for current doc, start new", application);
00231 retval = child_new(command_line, working_dir, application, document, label, image, context, message_id);
00232 }
00233 }
00234 }
00235 else
00236 {
00237
00238
00239 LOGPRINTF("process %s, not currently running start new", application);
00240 retval = child_new(command_line, working_dir, application, document, label, image, context, message_id);
00241 }
00242 }
00243
00244
00245 g_free(application);
00246 g_free(document);
00247
00248 LOGPRINTF("leave: retval %d", retval);
00249
00250 return retval;
00251 }
00252
00253
00254 gboolean task_stop(const char *command_line,
00255 eripc_context_t *context,
00256 const char *message_id)
00257 {
00258 LOGPRINTF("entry: `%s`", command_line);
00259
00260 gboolean retval = FALSE;
00261 gchar *application = NULL;
00262 gchar *document = NULL;
00263
00264 parse_commandline(command_line, &application, &document, NULL);
00265
00266 task_t *task = get_task(application, document);
00267 if (task)
00268 {
00269 if (task->proc && task->proc->ipc_service && task->proc->is_multidoc)
00270 {
00271 request_t *request = new_request(task, context, message_id);
00272 LOGPRINTF("found multidoc window, close child window");
00273 retval = child_window_close(task, request);
00274 }
00275 else
00276 {
00277 LOGPRINTF("found singledoc window, close child");
00278 retval = child_close(task);
00279 ipc_send_reply(context, message_id, retval);
00280 }
00281 }
00282
00283
00284 g_free(application);
00285 g_free(document);
00286
00287 LOGPRINTF("leave: retval %d", retval);
00288
00289 return retval;
00290 }
00291
00292
00293 gboolean task_rename(int xid, const char *new_document, const char* new_label)
00294 {
00295 LOGPRINTF("[%d] %s '%s'", xid, new_document, new_label);
00296 task_t *task = get_task_by_xid(xid);
00297 if (task == NULL) {
00298 ERRORPRINTF("unknown task: xid=%d", xid);
00299 return FALSE;
00300 }
00301 g_free(task->document);
00302 task->document = g_strdup(new_document);
00303 g_free(task->label);
00304 task->label = g_strdup(new_label);
00305 ipc_menu_rename_task(xid, task->label);
00306 return TRUE;
00307 }
00308
00309
00310 void task_activate_by_xid(int xid)
00311 {
00312 LOGPRINTF("entry xid=%d", xid);
00313 if (xid == FOLDER_XID)
00314 {
00315 process_activate_ctb();
00316 return;
00317 }
00318 task_t *task = get_task_by_xid(xid);
00319 if (task)
00320 {
00321 LOGPRINTF("found task, activate window %d", (gint) task->window);
00322 child_activate(task);
00323 }
00324 else
00325 {
00326 WARNPRINTF("task not found, xid=%d", xid);
00327 }
00328 }
00329
00330
00331 gboolean task_activate(const char *command_line)
00332 {
00333 LOGPRINTF("entry: `%s`", command_line);
00334
00335 gboolean retval = FALSE;
00336 gchar *application = NULL;
00337 gchar *document = NULL;
00338
00339 parse_commandline(command_line, &application, &document, NULL);
00340
00341 task_t *task = get_task(application, document);
00342 if (task)
00343 {
00344 LOGPRINTF("found task, activate window %d", (gint) task->window);
00345 retval = child_activate(task);
00346 }
00347 else
00348 {
00349 WARNPRINTF("task not found cmdline='%s'", command_line);
00350 }
00351
00352
00353 g_free(application);
00354 g_free(document);
00355
00356 LOGPRINTF("leave: retval %d", retval);
00357
00358 return retval;
00359 }
00360
00361
00362 #if (TESTING_ON)
00363 void print_task_list()
00364 {
00365 GSList *task_ptr = g_tasklist;
00366
00367 int i = 0;
00368 printf("%s() TASKS\n", __func__);
00369 while (task_ptr)
00370 {
00371 task_t *task = (task_t *) task_ptr->data;
00372 int pid = (task->proc) ? task->proc->pid : 0;
00373 printf(" [%d] proc_pid=%d window=%d app=%s doc=%s\n", i, pid,
00374 (guint)task->window, task->application, task->document);
00375
00376 task_ptr = task_ptr->next;
00377 i++;
00378 }
00379 }
00380 #endif
00381
00382
00383 const gchar *task_service_by_window(Window xid)
00384 {
00385 LOGPRINTF("entry: %d", (gint) xid);
00386
00387 task_t *task = get_task_by_xid(xid);
00388 if (task && task->proc && task->proc->ipc_service)
00389 {
00390 return task->proc->ipc_service;
00391 }
00392 return NULL;
00393 }
00394
00395
00396 gboolean task_add(const char *application,
00397 const char *document,
00398 const char *label,
00399 const char *image,
00400 const char *ipc_service,
00401 gint pid,
00402 Window xid)
00403 {
00404 LOGPRINTF("entry");
00405
00406 gboolean retval = FALSE;
00407
00408 task_t *task = get_task(application, document);
00409 proc_t *proc = process_get_by_pid(pid);
00410 if (proc && !task)
00411 {
00412 LOGPRINTF("task %s, %s, not found, add it...", application, document);
00413 task = tasklist_add(proc, application, document, label, image, xid);
00414 if (task)
00415 {
00416 retval = TRUE;
00417 }
00418 }
00419
00420 return retval;
00421 }
00422
00423
00424 gboolean task_cleanup_pid(GPid pid)
00425 {
00426 LOGPRINTF("entry: forced %d", g_forced_close);
00427
00428 gboolean result = tasklist_remove_pid(pid);
00429
00430 if (result && !g_forced_close)
00431 {
00432 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00433
00434 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00435
00436 process_activate_ctb();
00437 #endif
00438 }
00439
00440 g_forced_close = FALSE;
00441
00442 return result;
00443 }
00444
00445
00446 gboolean task_cleanup_window(Window xid)
00447 {
00448 LOGPRINTF("entry: xid %d, forced %d", (int) xid, g_forced_close);
00449
00450 gboolean result = tasklist_remove_window(xid);
00451
00452 if (result && !g_forced_close)
00453 {
00454 #if MACHINE_IS_DR800SG || MACHINE_IS_DR800S || MACHINE_IS_DR800SW
00455
00456 #elif MACHINE_IS_DR1000S || MACHINE_IS_DR1000SW
00457
00458 process_activate_ctb();
00459 #endif
00460 }
00461
00462 g_forced_close = FALSE;
00463
00464 return result;
00465 }
00466
00467
00468 gboolean task_startup_completed(proc_t *proc, Window window)
00469 {
00470 LOGPRINTF("entry");
00471
00472 GSList *task_ptr = g_tasklist;
00473 while (task_ptr)
00474 {
00475 task_t *task = (task_t *) task_ptr->data;
00476
00477 if (task->proc == proc)
00478 {
00479 if (window != 0)
00480 {
00481 task->window = window;
00482 LOGPRINTF("assigned window %d to %s, %s", (gint) task->window, task->application, task->document);
00483 }
00484
00485
00486 ipc_menu_add_task((gint)task->window, task->label);
00487
00488 return TRUE;
00489 }
00490 task_ptr = task_ptr->next;
00491 }
00492 return FALSE;
00493 }
00494
00495
00496 char* testing_task_get_list()
00497 {
00498 #if (TESTING_ON)
00499 char buffer[1000];
00500 char* cp = buffer;
00501 GSList *iter = g_tasklist;
00502 while (iter)
00503 {
00504 task_t* task = (task_t*) iter->data;
00505 strcpy(cp, task->application);
00506 cp += strlen(task->application);
00507 *cp++ = '|';
00508 strcpy(cp, task->document);
00509 cp += strlen(task->document);
00510 *cp++ = '\n';
00511
00512 iter = g_slist_next(iter);
00513 }
00514 *cp = 0;
00515 char* result = g_strdup(buffer);
00516 return result;
00517 #endif
00518 return g_strdup("no debug");
00519 }
00520
00521
00522
00523
00524
00525
00526 static gboolean child_new(const char *command,
00527 const char *working_dir,
00528 const char *application,
00529 const char *document,
00530 const char *label,
00531 const char *image,
00532 eripc_context_t *context,
00533 const char *message_id)
00534 {
00535 LOGPRINTF("entry");
00536
00537 gboolean retval = FALSE;
00538
00539 if ( g_check_child_window_source == 0
00540 && g_task_pending_source == 0 )
00541 {
00542
00543 if (working_dir && working_dir[0]=='\0')
00544 {
00545 working_dir = NULL;
00546 }
00547
00548 proc_t *proc = process_start(command, working_dir, NULL, NULL, PS_WAIT_STARTED);
00549 if (proc != NULL)
00550 {
00551 task_t *task = tasklist_add(proc, application, document, label, image, 0);
00552 request_t *request = new_request(task, context, message_id);
00553
00554
00555 busy_add_foreground(0, BUSY_DIALOG_DELAYED, NULL);
00556
00557 LOGPRINTF("pending task adding, wait for window id");
00558
00559
00560 g_check_child_window_source = g_timeout_add(TIMER_CHECK_WINDOW_MS, on_check_child_window, request);
00561
00562
00563 g_task_pending_source = g_timeout_add_seconds(TIMEOUT_CHILD_NEW, on_child_new_timeout, request);
00564
00565 retval = TRUE;
00566 }
00567 else
00568 {
00569 LOGPRINTF("error starting, return failure");
00570
00571 }
00572 }
00573 else
00574 {
00575 ERRORPRINTF("still waiting for another task to be started, refusing task [%s]", label);
00576 }
00577
00578 return retval;
00579 }
00580
00581
00582 static gboolean child_window_open(task_t *task,
00583 request_t *request)
00584 {
00585 LOGPRINTF("entry");
00586
00587 gboolean retval = FALSE;
00588
00589 if (task->proc && task->proc->ipc_service)
00590 {
00591 LOGPRINTF("pending task added, wait for on_window_open_callback");
00592 retval = ipc_send_open(task->proc->ipc_service, task->document, on_window_open_callback, request);
00593 }
00594
00595 return retval;
00596 }
00597
00598
00599 static request_t *new_request(task_t *task,
00600 eripc_context_t *context,
00601 const char *message_id)
00602 {
00603 LOGPRINTF("entry");
00604
00605 request_t *request = g_new0(request_t, 1);
00606 if (!request)
00607 {
00608 ERRORPRINTF("mem alloc failed");
00609 return FALSE;
00610 }
00611 request->task = task;
00612 request->context = context;
00613 request->message_id = g_strdup(message_id);
00614
00615 return request;
00616 }
00617
00618
00619 static void free_request(request_t *request)
00620 {
00621 LOGPRINTF("entry");
00622
00623 g_free(request->message_id);
00624 g_free(request);
00625 request = NULL;
00626 }
00627
00628
00629 static gboolean child_window_close(task_t *task,
00630 request_t *request)
00631 {
00632 LOGPRINTF("entry");
00633
00634 gboolean retval = FALSE;
00635
00636 if (task->proc && task->proc->ipc_service)
00637 {
00638 LOGPRINTF("wait for on_window_close_callback");
00639 retval = ipc_send_close(task->proc->ipc_service, task->document, on_window_close_callback, request);
00640 }
00641
00642 return retval;
00643 }
00644
00645
00646 static gboolean child_activate(task_t *task)
00647 {
00648 LOGPRINTF("entry");
00649
00650
00651 tasklist_set_first(task);
00652
00653
00654 window_activate(task->window);
00655
00656 return TRUE;
00657 }
00658
00659
00660 static gboolean child_close(task_t *task)
00661 {
00662 LOGPRINTF("entry");
00663
00664 if (task->proc)
00665 {
00666
00667 kill(task->proc->pid, SIGTERM);
00668 }
00669
00670
00671 g_child_terminate_source = g_timeout_add_seconds(TIMEOUT_CHILD_CLOSE, on_child_term_timeout, task);
00672
00673 return TRUE;
00674 }
00675
00676
00677 static gboolean on_child_new_timeout(gpointer data)
00678 {
00679 LOGPRINTF("entry");
00680
00681 request_t *request = data;
00682
00683 g_return_val_if_fail(request != NULL, FALSE);
00684
00685 if (g_check_child_window_source)
00686 {
00687 g_source_remove(g_check_child_window_source);
00688 g_check_child_window_source = 0;
00689 }
00690
00691 if (g_task_pending_source)
00692 {
00693 g_source_remove(g_task_pending_source);
00694 g_task_pending_source = 0;
00695 }
00696
00697 task_t *task = find_valid_task(request->task);
00698 if (task != NULL)
00699 {
00700 tasklist_remove_pid(request->task->proc->pid);
00701 }
00702
00703
00704 if (request->context && request->message_id)
00705 {
00706 ipc_send_reply_task_start(request->context, request->message_id, 2, NULL);
00707 }
00708 free_request(request);
00709
00710
00711 busy_remove_foreground(0);
00712
00713
00714 return FALSE;
00715 }
00716
00717
00718 static void check_num_tasks()
00719 {
00720 if (g_slist_length(g_tasklist) > MAX_TASKS)
00721 {
00722 LOGPRINTF("maximum number of tasks reached, remove oldest");
00723
00724
00725 GSList *list_last_task = g_slist_last(g_tasklist);
00726 task_t *last_task = list_last_task->data;
00727
00728 g_forced_close = TRUE;
00729
00730
00731 if (last_task->proc && last_task->proc->ipc_service
00732 && last_task->proc->is_multidoc)
00733 {
00734 request_t *request = new_request(last_task, NULL, NULL);
00735 child_window_close(last_task, request);
00736 }
00737 else
00738 {
00739 child_close(last_task);
00740 }
00741 }
00742 }
00743
00744
00745 static gboolean on_check_child_window(gpointer data)
00746 {
00747 LOGPRINTF("entry");
00748
00749 request_t *request = data;
00750
00751 if (request != NULL)
00752 {
00753 task_t *task = find_valid_task(request->task);
00754 if (task != NULL)
00755 {
00756 LOGPRINTF("looking for %s", task->application);
00757
00758 Window child_window = get_application_window(task->application);
00759 if (child_window == 0)
00760 {
00761
00762 return TRUE;
00763 }
00764 else
00765 {
00766 check_num_tasks();
00767
00768
00769 if (task->window == 0) {
00770 task->window = child_window;
00771 }
00772
00773 if (request->context && request->message_id)
00774 {
00775
00776 ipc_send_reply_task_start(request->context, request->message_id, 0, NULL);
00777 }
00778 free_request(request);
00779 }
00780 }
00781 else
00782 {
00783 WARNPRINTF("task not found");
00784
00785 if (request->context && request->message_id)
00786 {
00787
00788 ipc_send_reply_task_start(request->context, request->message_id, 3, NULL);
00789 }
00790 free_request(request);
00791 }
00792 }
00793 else
00794 {
00795 WARNPRINTF("request not found");
00796 }
00797
00798
00799 g_check_child_window_source = 0;
00800
00801
00802 if (g_task_pending_source)
00803 {
00804 g_source_remove(g_task_pending_source);
00805 g_task_pending_source = 0;
00806 }
00807
00808
00809 busy_remove_foreground(0);
00810
00811 return FALSE;
00812 }
00813
00814
00815 static void on_window_open_callback(eripc_context_t *context,
00816 const eripc_event_info_t *info,
00817 request_t *request)
00818 {
00819 LOGPRINTF("entry request [%p]", request);
00820
00821 gboolean retval = FALSE;
00822 gchar *errmsg = NULL;
00823 const eripc_arg_t *arg_array = info->args;
00824
00825 g_return_if_fail(request != NULL);
00826
00827 if (info->event_type != ERIPC_EVENT_REPLY)
00828 {
00829 WARNPRINTF("invalid event: %d", info->event_type);
00830 }
00831 else if ((arg_array == NULL) || (arg_array[0].type != ERIPC_TYPE_INT))
00832 {
00833 WARNPRINTF("invalid arguments in reply, task not added");
00834 }
00835 else if (arg_array[0].value.i < 0)
00836 {
00837 LOGPRINTF("child returned failure, task not added");
00838
00839 if (arg_array[1].type == ERIPC_TYPE_STRING)
00840 {
00841 LOGPRINTF("error message: %s", arg_array[1].value.s);
00842 errmsg = g_strdup(arg_array[1].value.s);
00843 }
00844
00845 task_t *new_task = find_valid_task(request->task);
00846 if (new_task)
00847 {
00848 tasklist_remove_window(new_task->window);
00849 }
00850 }
00851 else
00852 {
00853 task_t *old_task = NULL;
00854 task_t *task_data = NULL;
00855 GSList *task = g_tasklist;
00856
00857 Window child_window = arg_array[0].value.i;
00858
00859
00860
00861
00862 LOGPRINTF("task started in window: %d", (int) child_window);
00863
00864
00865
00866 while ( (task != NULL) && (task->data != NULL) )
00867 {
00868 task_data = task->data;
00869
00870 LOGPRINTF("check %s, %s; window %d", task_data->application, task_data->document, (int) task_data->window);
00871
00872 if (task_data->window == child_window)
00873 {
00874
00875 old_task = task_data;
00876 break;
00877 }
00878
00879 task = task->next;
00880 }
00881
00882 task_t *new_task = find_valid_task(request->task);
00883 if (new_task && (child_window > 0))
00884 {
00885 LOGPRINTF("task %s, %s; window %d", new_task->application, new_task->document, (int) child_window);
00886
00887 if (old_task == new_task)
00888 {
00889
00890 child_activate(old_task);
00891 }
00892 else
00893 {
00894 if (old_task)
00895 {
00896
00897 LOGPRINTF("remove old task %s, %s: window %d", old_task->application, old_task->document, (int) old_task->window);
00898 tasklist_remove_window(old_task->window);
00899 }
00900 else
00901 {
00902
00903 check_num_tasks();
00904 }
00905
00906
00907 ipc_menu_add_task(child_window, new_task->label);
00908
00909
00910 new_task->window = child_window;
00911
00912 if (old_task)
00913 {
00914
00915 LOGPRINTF("reactivate existing window");
00916 window_activate(child_window);
00917 }
00918 }
00919 }
00920
00921
00922 retval = TRUE;
00923 }
00924
00925 if (request != NULL)
00926 {
00927 if (request->message_id != NULL)
00928 {
00929
00930 if (retval == TRUE)
00931 {
00932 LOGPRINTF("return result to caller [%d], message_id [%s]", 0, request->message_id);
00933 ipc_send_reply_task_start(request->context, request->message_id, 0, NULL);
00934 }
00935 else
00936 {
00937 LOGPRINTF("return result to caller [%d], message_id [%s]", 4, request->message_id);
00938 ipc_send_reply_task_start(request->context, request->message_id, 4, errmsg);
00939 }
00940 }
00941 free_request(request);
00942 }
00943
00944 g_free(errmsg);
00945 }
00946
00947
00948 static void on_window_close_callback(eripc_context_t *context,
00949 const eripc_event_info_t *info,
00950 request_t *request)
00951 {
00952 LOGPRINTF("entry request [%p]", request);
00953
00954 gboolean retval = FALSE;
00955 const eripc_arg_t *arg_array = info->args;
00956
00957 if (request == NULL)
00958 {
00959 WARNPRINTF("request is null");
00960 }
00961 if (find_valid_task(request->task) == NULL)
00962 {
00963 WARNPRINTF("task not found [%p]", request->task);
00964 }
00965 else if (info->event_type != ERIPC_EVENT_REPLY)
00966 {
00967 WARNPRINTF("invalid event: %d", info->event_type);
00968 }
00969 else if ((arg_array == NULL) || (arg_array[0].type != ERIPC_TYPE_BOOL))
00970 {
00971 WARNPRINTF("invalid arguments in reply");
00972 }
00973 else if (arg_array[0].value.b == FALSE)
00974 {
00975 LOGPRINTF("child returned failure");
00976 }
00977 else
00978 {
00979
00980
00981
00982
00983 tasklist_remove_window(request->task->window);
00984 retval = TRUE;
00985 }
00986
00987 if (request != NULL)
00988 {
00989 if (request->message_id != NULL)
00990 {
00991
00992 LOGPRINTF("return result to caller [%d], message_id [%s]", retval, request->message_id);
00993 ipc_send_reply(request->context, request->message_id, retval);
00994 }
00995 free_request(request);
00996 }
00997 }
00998
00999
01000
01001 static gboolean on_child_term_timeout(gpointer data)
01002 {
01003 LOGPRINTF("entry");
01004
01005 task_t *task = data;
01006
01007 if (task->proc && (task->proc->pid > 0))
01008 {
01009
01010 kill(task->proc->pid, SIGKILL);
01011 }
01012
01013
01014 g_child_terminate_source = 0;
01015
01016
01017 return FALSE;
01018 }
01019
01020
01021 static task_t *tasklist_add(proc_t *proc, const char *application, const char *document,
01022 const char *label, const char *image, Window window)
01023 {
01024 LOGPRINTF("entry");
01025
01026 task_t *task = g_new0 (task_t, 1);
01027 if (!task)
01028 {
01029 ERRORPRINTF("mem alloc failed");
01030 return NULL;
01031 }
01032
01033 task->proc = proc;
01034 task->application = g_strdup(application);
01035 task->document = g_strdup(document);
01036 task->label = g_strdup(label);
01037 task->image = g_strdup(image);
01038 task->window = window;
01039
01040 g_tasklist = g_slist_prepend(g_tasklist, task);
01041
01042 LOGPRINTF("done. task %p [#tasks: %d]", task, g_slist_length(g_tasklist));
01043
01044 return task;
01045 }
01046
01047
01048 static void free_task(task_t *task)
01049 {
01050 g_free(task->application);
01051 g_free(task->document);
01052 g_free(task->label);
01053 g_free(task->image);
01054 g_free(task);
01055 task = NULL;
01056 }
01057
01058
01059 static gboolean tasklist_set_first(task_t *task)
01060 {
01061 LOGPRINTF("entry");
01062
01063 task_t *task_data = NULL;
01064 GSList *cur_task = g_tasklist;
01065
01066 while ( (cur_task != NULL) && (cur_task->data != NULL) )
01067 {
01068 task_data = cur_task->data;
01069 if (task_data == task)
01070 {
01071 ipc_menu_set_first_task(task->window);
01072
01073 g_tasklist = g_slist_delete_link(g_tasklist, cur_task);
01074 g_tasklist = g_slist_prepend(g_tasklist, task);
01075 LOGPRINTF("task set to first [#tasks: %d]", g_slist_length(g_tasklist));
01076 return TRUE;
01077 }
01078
01079 cur_task = cur_task->next;
01080 }
01081
01082 LOGPRINTF("no first task found [#tasks: %d]", g_slist_length(g_tasklist));
01083 return FALSE;
01084 }
01085
01086
01087 static gboolean tasklist_remove_pid(GPid pid)
01088 {
01089 LOGPRINTF("entry");
01090
01091 GSList *task = g_tasklist;
01092 gint npre = g_slist_length(g_tasklist);
01093
01094 while ( (task != NULL) && (task->data != NULL) )
01095 {
01096 task_t *task_data = task->data;
01097
01098 if (task_data->proc && (task_data->proc->pid == pid))
01099 {
01100 ipc_menu_remove_task(task_data->window);
01101 free_task(task_data);
01102
01103 g_tasklist = g_slist_delete_link(g_tasklist, task);
01104
01105
01106 task = g_tasklist;
01107 }
01108 else
01109 {
01110 task = task->next;
01111 }
01112 }
01113
01114 gint npost = g_slist_length(g_tasklist);
01115
01116 if (npre != npost)
01117 {
01118 LOGPRINTF("removed %d tasks, %d remaining", npre-npost, npost);
01119 return TRUE;
01120 }
01121 else
01122 {
01123 LOGPRINTF("no tasks found for pid %d", pid);
01124 return FALSE;
01125 }
01126 }
01127
01128
01129 static gboolean tasklist_remove_window(Window window)
01130 {
01131 LOGPRINTF("entry: xid %d", (int) window);
01132
01133 GSList *task = g_tasklist;
01134 gint npre = g_slist_length(g_tasklist);
01135 gboolean is_uds_task = FALSE;
01136
01137 while ( (task != NULL) && (task->data != NULL) )
01138 {
01139 task_t *task_data = task->data;
01140
01141 if (task_data->window == window)
01142 {
01143 ipc_menu_remove_task(task_data->window);
01144
01145 if (strcmp(task_data->application, "uds") == 0)
01146 {
01147 is_uds_task = TRUE;
01148 }
01149 free_task(task_data);
01150
01151 g_tasklist = g_slist_delete_link(g_tasklist, task);
01152
01153
01154 task = g_tasklist;
01155 }
01156 else
01157 {
01158 task = task->next;
01159 }
01160 }
01161
01162 gint npost = g_slist_length(g_tasklist);
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172 if (npre != npost)
01173 {
01174 LOGPRINTF("removed %d tasks, %d remaining", npre-npost, npost);
01175 return TRUE;
01176 }
01177 else
01178 {
01179 LOGPRINTF("no tasks found for window %d", (int) window);
01180 return FALSE;
01181 }
01182 }
01183
01184
01185 static task_t *find_valid_task(task_t *task)
01186 {
01187 if (task == NULL) return NULL;
01188
01189 task_t *task_data = NULL;
01190 GSList *cur_task = g_tasklist;
01191
01192 while ( (cur_task != NULL) && (cur_task->data != NULL) )
01193 {
01194 task_data = cur_task->data;
01195 if (task_data == task)
01196 {
01197 return task_data;
01198 }
01199 cur_task = cur_task->next;
01200 }
01201
01202 return NULL;
01203 }
01204
01205
01206 static task_t *get_task_by_xid(Window xid)
01207 {
01208 GSList *task_ptr = g_tasklist;
01209
01210 while (task_ptr)
01211 {
01212 task_t *cur_task = (task_t *) task_ptr->data;
01213
01214 if (cur_task->window == xid) return cur_task;
01215 task_ptr = task_ptr->next;
01216 }
01217 return NULL;
01218 }
01219
01220
01221 static task_t *get_task(const char *application, const char *document)
01222 {
01223 LOGPRINTF("entry");
01224
01225 GSList *task_ptr = g_tasklist;
01226 gchar *baseapp = g_path_get_basename(application);
01227
01228 while (task_ptr)
01229 {
01230 task_t *cur_task = (task_t *) task_ptr->data;
01231
01232 if (baseapp && cur_task->application && (strcmp(cur_task->application, baseapp) == 0) &&
01233 ((document == NULL) || (cur_task->document && (strcmp(cur_task->document, document) == 0))))
01234 {
01235 g_free(baseapp);
01236 return cur_task;
01237 }
01238 task_ptr = task_ptr->next;
01239 }
01240
01241 g_free(baseapp);
01242 return NULL;
01243 }
01244
01245
01246 gboolean parse_commandline(const gchar *command_line, gchar **application, gchar **document, gchar **arguments)
01247 {
01248 char **argv_ptr = NULL;
01249 GError *error = NULL;
01250 gchar *app = NULL;
01251 gchar *doc = NULL;
01252 gchar *arg = NULL;
01253 gint argc = 0;
01254
01255 LOGPRINTF("enter");
01256
01257 g_shell_parse_argv(command_line, &argc, &argv_ptr, &error);
01258 if (error)
01259 {
01260 WARNPRINTF("Execution of '%s' failed with error: %s", command_line, error->message);
01261 g_error_free(error);
01262 return FALSE;
01263 }
01264
01265
01266
01267 app = g_path_get_basename(argv_ptr[0]);
01268
01269 if (argc > 1)
01270 {
01271 doc = g_strdup(argv_ptr[argc-1]);
01272
01273
01274 arg = g_strjoinv(" ", &argv_ptr[1]);
01275 }
01276
01277
01278
01279 if (application != NULL)
01280 {
01281 LOGPRINTF("app `%s`", app);
01282 *application = app;
01283 }
01284 else
01285 {
01286 g_free(app);
01287 }
01288
01289 if (document != NULL)
01290 {
01291 LOGPRINTF("doc `%s`", doc);
01292 *document = doc;
01293 }
01294 else
01295 {
01296 g_free(doc);
01297 }
01298
01299 if (arguments != NULL)
01300 {
01301 LOGPRINTF("arg `%s`", arg);
01302 *arguments = arg;
01303 }
01304 else
01305 {
01306 g_free(arg);
01307 }
01308
01309 g_strfreev(argv_ptr);
01310
01311 return TRUE;
01312 }