Update License
[platform/framework/web/data-provider-master.git] / util_liveinfo / src / liveinfo.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <getopt.h>
20 #include <errno.h>
21 #include <libgen.h>
22 #include <sys/types.h>
23 #include <sys/wait.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <termios.h>
27 #include <sys/shm.h>
28 #include <sys/ipc.h>
29
30 #include <X11/Xlib.h>
31 #include <X11/extensions/Xdamage.h>
32 #include <X11/extensions/Xfixes.h>
33 #include <X11/extensions/XShm.h>
34 #include <X11/Xutil.h>
35
36 #include <glib.h>
37 #include <glib-object.h>
38
39 #include <packet.h>
40 #include <com-core_packet.h>
41 #include <com-core.h>
42
43 #include <livebox-service.h>
44
45 #include <Ecore.h>
46
47 #include "liveinfo.h"
48 #include "node.h"
49
50 #define PROMPT "liveinfo "
51
52 struct package {
53         int primary;
54         char *pkgid;
55
56         int pid;
57         char *slavename;
58         char *abi;
59         int refcnt;
60         int fault_count;
61         int inst_count;
62 };
63
64 struct instance {
65         char *id;
66         char *cluster;
67         char *category;
68         double period;
69         char *state;
70         int width;
71         int height;
72 };
73
74 struct slave {
75         int pid;
76         char *pkgname;
77         char *abi;
78         int secured;
79         int refcnt;
80         int fault_count;
81         char *state;
82         int loaded_inst;
83         int loaded_pkg;
84         double ttl;
85 };
86
87 enum command {
88         NOP,
89         PKG_LIST,
90         INST_LIST,
91         SLAVE_LIST,     
92         INST_CTRL,
93         SLAVE_CTRL,
94         MASTER_CTRL,
95 };
96
97 static struct info {
98         int fifo_handle;
99         int fd;
100         Ecore_Fd_Handler *fd_handler;
101         Ecore_Fd_Handler *in_handler;
102
103         struct node *rootdir;
104         struct node *curdir;
105         struct node *targetdir;
106
107         enum command cmd;
108
109         int input_fd;
110         int verbose;
111
112         int age;
113
114         char *history[1024];
115         int history_top;
116         int history_idx;
117
118         struct node *quick_search_node;
119         int quick_idx;
120 } s_info = {
121         .fifo_handle = -EINVAL,
122         .fd = -EINVAL,
123         .fd_handler = NULL,
124         .in_handler = NULL,
125         .rootdir = NULL,
126         .curdir = NULL,
127         .targetdir = NULL,
128         .cmd = NOP,
129         .input_fd = STDIN_FILENO,
130         .verbose = 0,
131         .age = 0,
132         .history = { 0, },
133         .history_top = 0,
134         .history_idx = 0,
135         .quick_search_node = NULL,
136         .quick_idx = 0,
137 };
138
139 char *optarg;
140 int errno;
141 int optind;
142 int optopt;
143 int opterr;
144
145 static Eina_Bool input_cb(void *data, Ecore_Fd_Handler *fd_handler);
146
147 static Eina_Bool process_line_cb(void *data)
148 {
149         input_cb(NULL, NULL);
150         return ECORE_CALLBACK_CANCEL;
151 }
152
153 static inline void prompt(const char *cmdline)
154 {
155         char *path;
156
157         if (s_info.input_fd != STDIN_FILENO) {
158                 /* To prevent recursive call, add function to the main loop (idler) */
159                 ecore_idler_add(process_line_cb, NULL);
160                 return;
161         }
162
163         path = node_to_abspath(s_info.curdir);
164         printf(PROMPT"%s # %s", path, cmdline ? cmdline : "");
165         free(path);
166 }
167
168 static void provider_del_cb(struct node *node)
169 {
170         struct slave *info;
171
172         info = node_data(node);
173         if (!info)
174                 return;
175
176         free(info->pkgname);
177         free(info->abi);
178         free(info->state);
179         free(info);
180 }
181
182 static void package_del_cb(struct node *node)
183 {
184         struct package *info;
185
186         info = node_data(node);
187         if (!info)
188                 return;
189
190         free(info->pkgid);
191         free(info->slavename);
192         free(info->abi);
193         free(info);
194 }
195
196 static void inst_del_cb(struct node *node)
197 {
198         struct instance *info;
199
200         info = node_data(node);
201         if (!info)
202                 return;
203
204         free(info->id);
205         free(info->cluster);
206         free(info->category);
207         free(info->state);
208         free(info);
209 }
210
211 static inline void ls(void)
212 {
213         struct node *node;
214         int cnt = 0;
215         int is_package;
216         int is_provider;
217         int is_instance;
218         struct node *next_node;
219
220         if (!(node_mode(s_info.targetdir) & NODE_READ)) {
221                 printf("Access denied\n");
222                 return;
223         }
224
225         is_package = node_name(s_info.targetdir) && !strcmp(node_name(s_info.targetdir), "package");
226         is_provider = !is_package && node_name(s_info.targetdir) && !strcmp(node_name(s_info.targetdir), "provider");
227         is_instance = !is_package && !is_provider && node_parent(s_info.targetdir) && node_name(node_parent(s_info.targetdir)) && !strcmp(node_name(node_parent(s_info.targetdir)), "package");
228
229         node = node_child(s_info.targetdir);
230         while (node) {
231                 if (is_package) {
232                         struct package *info;
233
234                         next_node = node_next_sibling(node);
235                         if (node_age(node) != s_info.age) {
236                                 node_delete(node, package_del_cb);
237                                 node = next_node;
238                                 continue;
239                         }
240
241                         info = node_data(node);
242                         printf(" %3d %20s %5s ", info->inst_count, info->slavename ? info->slavename : "(none)", info->abi ? info->abi : "?");
243                 } else if (is_provider) {
244                         struct slave *info;
245
246                         next_node = node_next_sibling(node);
247                         if (node_age(node) != s_info.age) {
248                                 node_delete(node, provider_del_cb);
249                                 node = next_node;
250                                 continue;
251                         }
252
253                         info = node_data(node);
254                         printf("%6d %3d %5s %5.2f ", info->pid, info->loaded_inst, info->abi ? info->abi : "?", info->ttl);
255                 } else if (is_instance) {
256                         struct instance *info;
257                         struct stat stat;
258                         char buf[4096];
259
260                         next_node = node_next_sibling(node);
261
262                         if (node_age(node) != s_info.age) {
263                                 node_delete(node, inst_del_cb);
264                                 node = next_node;
265                                 continue;
266                         }
267
268                         info = node_data(node);
269
270                         printf(" %5.2f %6s %10s %10s %4dx%-4d ", info->period, info->state, info->cluster, info->category, info->width, info->height);
271                         snprintf(buf, sizeof(buf), "/opt/usr/share/live_magazine/reader/%s", node_name(node));
272                         if (lstat(buf, &stat) < 0)
273                                 printf("%3d ERR ", errno);
274                         else
275                                 printf("%2.2lf KB ", (double)stat.st_size / 1024.0f);
276                 }
277
278                 if (node_type(node) == NODE_DIR)
279                         printf("%s/", node_name(node));
280                 else if (node_type(node) == NODE_FILE)
281                         printf("%s", node_name(node));
282
283                 printf("\n");
284                 node = node_next_sibling(node);
285                 cnt++;
286         }
287
288         printf("Total: %d\n", cnt);
289 }
290
291 static void send_slave_list(void)
292 {
293         struct packet *packet;
294
295         if (s_info.cmd != NOP) {
296                 printf("Previous command is not finished\n");
297                 return;
298         }
299
300         packet = packet_create_noack("slave_list", "d", 0.0f);
301         if (!packet) {
302                 printf("Failed to create a packet\n");
303                 return;
304         }
305
306         com_core_packet_send_only(s_info.fd, packet);
307         packet_destroy(packet);
308         s_info.cmd = SLAVE_LIST;
309         s_info.age++;
310 }
311
312 /*!
313  * var = debug, slave_max_load
314  * cmd = set / get
315  */
316 static void send_command(const char *cmd, const char *var, const char *val)
317 {
318         struct packet *packet;
319
320         if (s_info.cmd != NOP) {
321                 printf("Previous command is not finished\n");
322                 return;
323         }
324
325         packet = packet_create_noack("master_ctrl", "sss", cmd, var, val);
326         com_core_packet_send_only(s_info.fd, packet);
327         packet_destroy(packet);
328         s_info.cmd = MASTER_CTRL;
329         s_info.age++;
330 }
331
332 static int pkglist_cb(const char *appid, const char *lbid, int is_prime, void *data)
333 {
334         struct node *parent = data;
335         struct node *node;
336         struct package *info;
337
338         node = node_find(parent, lbid);
339         if (node) {
340                 info = node_data(node);
341                 if (!info) {
342                         printf("Invalid node\n");
343                         return -EINVAL;
344                 }
345
346                 free(info->pkgid);
347                 info->pkgid = strdup(appid);
348                 if (!info->pkgid) {
349                         printf("Error: %s\n", strerror(errno));
350                         return -ENOMEM;
351                 }
352
353                 node_set_age(node, s_info.age);
354                 return 0;
355         }
356
357         info = calloc(1, sizeof(*info));
358         if (!info) {
359                 printf("Error: %s\n", strerror(errno));
360                 return -ENOMEM;
361         }
362
363         info->pkgid = strdup(appid);
364         if (!info->pkgid) {
365                 printf("Error: %s\n", strerror(errno));
366                 free(info);
367                 return -ENOMEM;
368         }
369
370         info->primary = is_prime;
371
372         node = node_create(parent, lbid, NODE_DIR);
373         if (!node) {
374                 free(info->pkgid);
375                 free(info);
376                 return -ENOMEM;
377         }
378
379         node_set_mode(node, NODE_READ | NODE_EXEC);
380         node_set_data(node, info);
381         node_set_age(node, s_info.age);
382         return 0;
383 }
384
385 static void send_pkg_list(void)
386 {
387         struct packet *packet;
388
389         if (s_info.cmd != NOP) {
390                 printf("Previous command is not finished\n");
391                 return;
392         }
393
394         packet = packet_create_noack("pkg_list", "d", 0.0f);
395         if (!packet) {
396                 printf("Failed to create a packet\n");
397                 return;
398         }
399
400         com_core_packet_send_only(s_info.fd, packet);
401         packet_destroy(packet);
402         s_info.cmd = PKG_LIST;
403         s_info.age++;
404
405         livebox_service_get_pkglist(pkglist_cb, s_info.targetdir);
406 }
407
408 static void send_inst_delete(void)
409 {
410         struct packet *packet;
411         struct node *parent;
412         const char *name;
413         struct instance *inst;
414
415         if (s_info.cmd != NOP) {
416                 printf("Previous command is not finished\n");
417                 return;
418         }
419
420         parent = node_parent(s_info.targetdir);
421         if (!parent) {
422                 printf("Invalid argument\n");
423                 return;
424         }
425
426         if (!node_parent(parent)) {
427                 printf("Invalid argument\n");
428                 return;
429         }
430
431         name = node_name(node_parent(parent));
432         if (!name || strcmp(name, "package")) {
433                 printf("Invalid argument\n");
434                 return;
435         }
436
437         inst = node_data(s_info.targetdir);
438         name = node_name(parent);
439
440         packet = packet_create_noack("pkg_ctrl", "sss", "rminst", name, inst->id);
441         if (!packet) {
442                 printf("Failed to create a packet\n");
443                 return;
444         }
445
446         com_core_packet_send_only(s_info.fd, packet);
447         packet_destroy(packet);
448         s_info.cmd = INST_CTRL;
449         s_info.age++;
450 }
451
452 static void send_inst_list(const char *pkgname)
453 {
454         struct packet *packet;
455
456         if (s_info.cmd != NOP) {
457                 printf("Previous command is not finished\n");
458                 return;
459         }
460
461         packet = packet_create_noack("inst_list", "s", pkgname);
462         if (!packet) {
463                 printf("Failed to create a packet\n");
464                 return;
465         }
466
467         com_core_packet_send_only(s_info.fd, packet);
468         packet_destroy(packet);
469         s_info.cmd = INST_LIST;
470         s_info.age++;
471 }
472
473 static inline void help(void)
474 {
475         printf("liveinfo - Livebox utility\n");
476         printf("------------------------------ [Option] ------------------------------\n");
477         printf("-b Batch mode\n");
478         printf("------------------------------ [Command list] ------------------------------\n");
479         printf("\e[32mcd [PATH] - Change directory\e[0m\n");
480         printf("\e[32mls [ | PATH] - List up content as a file\e[0m\n");
481         printf("\e[32mrm [PKG_ID|INST_ID] - Delete package or instance\e[0m\n");
482         printf("\e[32mstat [path] - Display the information of given path\e[0m\n");
483         printf("\e[32mset [debug] [on|off] Set the control variable of master provider\e[0m\n");
484         printf("\e[32mx damage Pix x y w h - Create damage event for given pixmap\e[0m\n");
485         printf("\e[32mx move Pix x y - Move the window\e[0m\n");
486         printf("\e[32mx resize Pix w h - Resize the window\e[0m\n");
487         printf("\e[32mx map Pix - Show the window\e[0m\n");
488         printf("\e[32mx unmap Pix - Hide the window\e[0m\n");
489         printf("\e[32msh [command] Execute shell command, [command] should be abspath\e[0m\n");
490         printf("\e[32mexit - \e[0m\n");
491         printf("\e[32mquit - \e[0m\n");
492         printf("----------------------------------------------------------------------------\n");
493 }
494
495 static inline void init_directory(void)
496 {
497         struct node *node;
498         s_info.rootdir = node_create(NULL, NULL, NODE_DIR);
499         if (!s_info.rootdir)
500                 return;
501         node_set_mode(s_info.rootdir, NODE_READ | NODE_EXEC);
502
503         node = node_create(s_info.rootdir, "provider", NODE_DIR);
504         if (!node) {
505                 node_destroy(s_info.rootdir);
506                 s_info.rootdir = NULL;
507                 return;
508         }
509         node_set_mode(node, NODE_READ | NODE_EXEC);
510
511         node = node_create(s_info.rootdir, "package", NODE_DIR);
512         if (!node) {
513                 node_destroy(node_child(s_info.rootdir));
514                 node_destroy(s_info.rootdir);
515                 s_info.rootdir = NULL;
516                 return;
517         }
518         node_set_mode(node, NODE_READ | NODE_EXEC);
519
520         s_info.curdir = s_info.rootdir;
521         return;
522 }
523
524 static inline void fini_directory(void)
525 {
526 }
527
528 static inline struct node *update_target_dir(const char *cmd)
529 {
530         struct node *node;
531
532         node = (*cmd == '/') ? s_info.rootdir : s_info.curdir;
533         node = node_find(node, cmd);
534
535         return node;
536 }
537
538 static int get_token(const char *src, char *out)
539 {
540         int len = 0;
541         while (*src && *src == ' ') src++;
542
543         if (!*src)
544                 return 0;
545
546         while (*src && *src != ' ') {
547                 *out++ = *src++;
548                 len++;
549         }
550
551         *out = '\0';
552         return len;
553 }
554
555 static inline int do_stat(const char *cmd)
556 {
557         int i;
558         struct node *node;
559         struct node *parent;
560         char *tmp;
561         enum stat_type {
562                 PKG_INSTANCE = 0x01,
563                 PKG,
564                 PROVIDER_INSTANCE,
565                 PROVIDER,
566                 ROOT,
567         } type;
568
569         cmd += 5;
570         while (*cmd && *cmd == ' ') cmd++;
571
572         if (!*cmd){
573                 printf("Invalid argument\n");
574                 return -EINVAL;
575         }
576
577         node = node_find(*cmd == '/' ? s_info.rootdir : s_info.curdir, cmd);
578         if (!node) {
579                 printf("Invalid path\n");
580                 return -EINVAL;
581         }
582
583         i = 0;
584         type = ROOT;
585         parent = node_parent(node);
586         while (parent) {
587                 if (!node_name(parent)) {
588                         printf("%s has no info\n", node_name(node));
589                         return -EINVAL;
590                 } else if (!strcmp(node_name(parent), "package")) {
591                         type = (i == 0) ? PKG : PKG_INSTANCE;
592                         break;
593                 } else if (!strcmp(node_name(parent), "provider")){
594                         type = (i == 0) ? PROVIDER : PROVIDER_INSTANCE;
595                         break;
596                 }
597
598                 parent = node_parent(parent);
599                 i++;
600                 if (i > 1) {
601                         printf("%s is invalid path\n", node_name(node));
602                         return -EINVAL;
603                 }
604         }
605
606         switch (type){
607         case PKG:
608                 tmp = livebox_service_i18n_name(node_name(node), NULL);
609                 printf("Name: %s (", tmp);
610                 free(tmp);
611
612                 i = livebox_service_is_enabled(node_name(node));
613                 printf("%s)\n", i ? "enabled" : "disabled");
614
615                 tmp = livebox_service_i18n_icon(node_name(node), NULL);
616                 printf("Icon: %s\n", tmp);
617                 free(tmp);
618
619                 tmp = livebox_service_provider_name(node_name(node));
620                 printf("Provider: %s (content:", tmp);
621                 free(tmp);
622
623                 tmp = livebox_service_content(node_name(node));
624                 printf("%s)\n", tmp);
625                 free(tmp);
626
627                 tmp = livebox_service_lb_script_path(node_name(node));
628                 printf("LB Script: %s (", tmp);
629                 free(tmp);
630
631                 tmp = livebox_service_lb_script_group(node_name(node));
632                 printf("%s)\n", tmp);
633                 free(tmp);
634
635                 tmp = livebox_service_pd_script_path(node_name(node));
636                 printf("PD Script: %s (", tmp);
637                 free(tmp);
638
639                 tmp = livebox_service_pd_script_group(node_name(node));
640                 printf("%s)\n", tmp);
641                 free(tmp);
642
643                 i = livebox_service_mouse_event(node_name(node));
644                 printf("Mouse event: %s\n", i ? "enabled" : "disabled");
645
646                 i = livebox_service_touch_effect(node_name(node));
647                 printf("Touch effect: %s\n", i ? "enabled" : "disabled");
648                 break;
649         case PROVIDER:
650                 printf("Not supported yet\n");
651                 break;
652         case PKG_INSTANCE:
653                 printf("Not supported yet\n");
654                 break;
655         case PROVIDER_INSTANCE:
656                 printf("Not supported yet\n");
657                 break;
658         case ROOT:
659                 printf("Not supported yet\n");
660                 break;
661         }
662
663         return 0;
664 }
665
666 static inline int do_set(const char *cmd)
667 {
668         int i;
669         char variable[4096] = { '0', };
670
671         cmd += 4;
672         i = get_token(cmd, variable);
673
674         cmd += i;
675         while (*cmd && *cmd == ' ') cmd++;
676
677         if (!i || !*cmd) {
678                 printf("Invalid argument(%s): set [VAR] [VAL]\n", cmd);
679                 return -EINVAL;
680         }
681
682         send_command("set", variable, cmd);
683         return 0;
684 }
685
686 static inline int do_get(const char *cmd)
687 {
688         cmd += 4;
689
690         while (*cmd && *cmd == ' ') cmd++;
691         if (!*cmd) {
692                 printf("Invalid argument(%s): get [VAR]\n", cmd);
693                 return -EINVAL;
694         }
695
696         send_command("get", cmd, "");
697         return 0;
698 }
699
700 static inline int do_ls(const char *cmd)
701 {
702         const char *name;
703         struct node *parent;
704
705         cmd += 2;
706
707         while (*cmd && *cmd == ' ')
708                 cmd++;
709
710         s_info.targetdir = *cmd ? update_target_dir(cmd) : s_info.curdir;
711         if (!s_info.targetdir) {
712                 printf("%s is not exists\n", cmd);
713                 return -ENOENT;
714         }
715
716         name = node_name(s_info.targetdir);
717         if (name) {
718                 if (!strcmp(name, "package")) {
719                         if (s_info.cmd == NOP) {
720                                 send_pkg_list();
721                                 return 0;
722                         }
723
724                         printf("Waiting the server response\n");
725                         return -EBUSY;
726                 } else if (!strcmp(name, "provider")) {
727                         if (s_info.cmd == NOP) {
728                                 send_slave_list();
729                                 return 0;
730                         }
731
732                         printf("Waiting the server response\n");
733                         return -EBUSY;
734                 }
735         }
736
737         parent = node_parent(s_info.targetdir);
738         if (parent && node_name(parent)) {
739                 if (!strcmp(node_name(parent), "package")) {
740                         if (s_info.cmd != NOP) {
741                                 printf("Waiting the server response\n");
742                                 return -EBUSY;
743                         }
744
745                         send_inst_list(name);
746                         return 0;
747                 }
748         }
749
750         ls();
751         return -1;
752 }
753
754 static inline int do_cd(const char *cmd)
755 {
756         cmd += 2;
757
758         while (*cmd && *cmd == ' ')
759                  cmd++;
760
761         if (!*cmd)
762                 return -1;
763
764         if (s_info.cmd != NOP) {
765                 printf("Waiting the server response\n");
766                 return -EBUSY;
767         }
768
769         s_info.targetdir = update_target_dir(cmd);
770         if (!s_info.targetdir) {
771                 printf("%s is not exists\n", cmd);
772                 return -ENOENT;
773         }
774
775         if (node_type(s_info.targetdir) != NODE_DIR) {
776                 printf("Unable change directory to %s\n", cmd);
777                 return -EINVAL;
778         }
779
780         if (!(node_mode(s_info.targetdir) & NODE_EXEC)) {
781                 printf("Access denied %s\n", cmd);
782                 return -EACCES;
783         }
784
785         s_info.curdir = s_info.targetdir;
786         return -1;
787 }
788
789 static inline int do_rm(const char *cmd)
790 {
791         cmd += 2;
792         while (*cmd && *cmd == ' ') cmd++;
793         if (!*cmd)
794                 return -1;
795
796         if (s_info.cmd != NOP) {
797                 printf("Waiting the server response\n");
798                 return -EBUSY;
799         }
800
801         s_info.targetdir = update_target_dir(cmd);
802         if (!s_info.targetdir) {
803                 printf("%s is not exists\n", cmd);
804                 return -ENOENT;
805         }
806
807         if (!(node_mode(s_info.targetdir) & NODE_WRITE)) {
808                 printf("Access denied %s\n", cmd);
809                 return -EACCES;
810         }
811
812         send_inst_delete();
813         return 0;
814 }
815
816 #if !defined(WCOREDUMP)
817 #define WCOREDUMP(a)    0
818 #endif
819
820 static inline void do_sh(const char *cmd)
821 {
822         pid_t pid;
823
824         cmd += 3;
825
826         while (*cmd && *cmd == ' ') cmd++;
827         if (!*cmd)
828                 return;
829
830         pid = fork();
831         if (pid == 0) {
832                 char command[256];
833                 int idx;
834                 idx = 0;
835
836                 while (idx < (sizeof(command) - 1) && *cmd && *cmd != ' ')
837                         command[idx++] = *cmd++;
838                 command[idx] = '\0';
839
840                 if (execl(command, cmd, NULL) < 0)
841                         printf("Failed to execute: %s\n", strerror(errno));
842
843                 exit(0);
844         } else if (pid < 0) {
845                 printf("Failed to create a new process: %s\n", strerror(errno));
846         } else {
847                 int status;
848                 if (waitpid(pid, &status, 0) < 0) {
849                         printf("error: %s\n", strerror(errno));
850                 } else {
851                         if (WIFEXITED(status)) {
852                                 printf("Exit: %d\n", WEXITSTATUS(status));
853                         } else if (WIFSIGNALED(status)) {
854                                 printf("Terminated by %d %s\n", WTERMSIG(status), WCOREDUMP(status) ? " - core generated" : "");
855                         } else if (WIFSTOPPED(status)) {
856                                 printf("Stopped by %d\n", WSTOPSIG(status));
857                         } else if (WIFCONTINUED(status)) {
858                                 printf("Child is resumed\n");
859                         }
860                 }
861         }
862 }
863
864 static inline int get_pixmap_size(Display *disp, Pixmap id, int *x, int *y, unsigned int *w, unsigned int *h)
865 {
866         Window dummy_win;
867         unsigned int dummy_border, dummy_depth;
868         int _x;
869         int _y;
870
871         if (!x)
872                 x = &_x;
873         if (!y)
874                 y = &_y;
875
876         if (!XGetGeometry(disp, id, &dummy_win, x, y, w, h, &dummy_border, &dummy_depth))
877                 return -EFAULT;
878
879         return 0;
880 }
881
882 static inline int do_capture(Display *disp, Pixmap id, const char *filename)
883 {
884         XShmSegmentInfo si;
885         XImage *xim;
886         Visual *visual;
887         unsigned int w;
888         unsigned int h;
889         int bufsz;
890         int fd;
891         Screen *screen;
892
893         screen = DefaultScreenOfDisplay(disp);
894         visual = DefaultVisualOfScreen(screen);
895
896         if (get_pixmap_size(disp, id, NULL, NULL, &w, &h) < 0) {
897                 printf("Failed to get size of a pixmap\n");
898                 return -EINVAL;
899         }
900
901         printf("Pixmap size: %dx%d\n", w, h);
902         bufsz = w * h * sizeof(int);
903
904         si.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0666);
905         if (si.shmid < 0) {
906                 printf("shmget: %s\n", strerror(errno));
907                 return -EFAULT;
908         }
909
910         si.readOnly = False;
911         si.shmaddr = shmat(si.shmid, NULL, 0);
912         if (si.shmaddr == (void *)-1) {
913
914                 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
915                         printf("shmctl: %s\n", strerror(errno));
916
917                 return -EFAULT;
918         }
919
920         /*!
921          * \NOTE
922          * Use the 24 bits Pixmap for Video player
923          */
924         xim = XShmCreateImage(disp, visual, 24 /* (depth << 3) */, ZPixmap, NULL, &si, w, h);
925         if (xim == NULL) {
926                 if (shmdt(si.shmaddr) < 0)
927                         printf("shmdt: %s\n", strerror(errno));
928
929                 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
930                         printf("shmctl: %s\n", strerror(errno));
931
932                 return -EFAULT;
933         }
934
935         xim->data = si.shmaddr;
936         XShmAttach(disp, &si);
937
938         XShmGetImage(disp, id, xim, 0, 0, 0xFFFFFFFF);
939         XSync(disp, False);
940
941         fd = open(filename, O_CREAT | O_RDWR, 0644);
942         if (fd >= 0) {
943                 if (write(fd, xim->data, bufsz) != bufsz)
944                         printf("Data is not fully written\n");
945
946                 close(fd);
947         } else {
948                 printf("Error: %sn\n", strerror(errno));
949         }
950
951         XShmDetach(disp, &si);
952         XDestroyImage(xim);
953
954         if (shmdt(si.shmaddr) < 0)
955                 printf("shmdt: %s\n", strerror(errno));
956
957         if (shmctl(si.shmid, IPC_RMID, 0) < 0)
958                 printf("shmctl: %s\n", strerror(errno));
959
960         return 0;
961 }
962
963 static inline void do_x(const char *cmd)
964 {
965         Display *disp;
966
967         cmd += 2;
968
969         while (*cmd && *cmd == ' ') cmd++;
970         if (!*cmd)
971                 return;
972
973         disp = XOpenDisplay(NULL);
974         if (!disp) {
975                 printf("Failed to connect to the X\n");
976                 return;
977         }
978
979         if (!strncasecmp(cmd, "damage ", 7)) {
980                 unsigned int winId;
981                 XRectangle rect;
982                 XserverRegion region;
983                 int x, y, w, h;
984
985                 cmd += 7;
986
987                 if (sscanf(cmd, "%u %d %d %d %d", &winId, &x, &y, &w, &h) != 5) {
988                         printf("Invalid argument\nx damage WINID_DEC X Y W H\n");
989                         return;
990                 }
991                 rect.x = x;
992                 rect.y = y;
993                 rect.width = w;
994                 rect.height = h;
995                 region = XFixesCreateRegion(disp, &rect, 1);
996                 XDamageAdd(disp, winId, region);
997                 XFixesDestroyRegion(disp, region);
998                 XFlush(disp);
999
1000                 printf("Damage: %u %d %d %d %d\n", winId, x, y, w, h);
1001         } else if (!strncasecmp(cmd, "capture ", 8)) {
1002                 unsigned int winId;
1003                 char filename[256];
1004
1005                 cmd += 8;
1006
1007                 if (sscanf(cmd, "%u %255[^ ]", &winId, filename) != 2) {
1008                         printf("Invalid argument\nx capture WINID_DEC FILENAME (%s)\n", cmd);
1009                         return;
1010                 }
1011                 if (do_capture(disp, winId, filename) == 0)
1012                         printf("Captured: %s\n", filename);
1013         } else if (!strncasecmp(cmd, "resize ", 7)) {
1014                 unsigned int winId;
1015                 int w;
1016                 int h;
1017
1018                 cmd += 7;
1019
1020                 if (sscanf(cmd, "%u %d %d", &winId, &w, &h) != 3) {
1021                         printf("Invalid argument\nx resize WINID_DEC W H\n");
1022                         return;
1023                 }
1024
1025                 XResizeWindow(disp, winId, w, h);
1026                 printf("Resize: %u %d %d\n", winId, w, h);
1027         } else if (!strncasecmp(cmd, "move ", 5)) {
1028                 unsigned int winId;
1029                 int x;
1030                 int y;
1031
1032                 cmd += 5;
1033                 if (sscanf(cmd, "%u %d %d", &winId, &x, &y) != 3) {
1034                         printf("Invalid argument\nx move WINID_DEC X Y\n");
1035                         return;
1036                 }
1037
1038                 XMoveWindow(disp, winId, x, y);
1039                 printf("Move: %u %d %d\n", winId, x, y);
1040         } else if (!strncasecmp(cmd, "map ", 4)) {
1041                 unsigned int winId;
1042                 cmd += 4;
1043                 if (sscanf(cmd, "%u", &winId) != 1) {
1044                         printf("Invalid argument\nx map WINID_DEC\n");
1045                         return;
1046                 }
1047                 XMapRaised(disp, winId);
1048                 printf("Map: %u\n", winId);
1049         } else if (!strncasecmp(cmd, "unmap ", 6)) {
1050                 unsigned int winId;
1051                 cmd += 6;
1052                 if (sscanf(cmd, "%u", &winId) != 1) {
1053                         printf("Invalid argument\nx unmap WINID_DEC\n");
1054                         return;
1055                 }
1056                 XUnmapWindow(disp, winId);
1057                 printf("Unmap: %u\n", winId);
1058         } else {
1059                 printf("Unknown command\n");
1060         }
1061
1062         XCloseDisplay(disp);
1063 }
1064
1065 static inline void put_command(const char *cmd)
1066 {
1067         if (s_info.history[s_info.history_top]) {
1068                 free(s_info.history[s_info.history_top]);
1069                 s_info.history[s_info.history_top] = NULL;
1070         }
1071
1072         s_info.history[s_info.history_top] = strdup(cmd);
1073         s_info.history_top = (s_info.history_top + !!s_info.history[s_info.history_top]) % (sizeof(s_info.history) / sizeof(s_info.history[0]));
1074 }
1075
1076 static inline const char *get_command(int idx)
1077 {
1078         idx = s_info.history_top + idx;
1079         while (idx < 0)
1080                 idx += (sizeof(s_info.history) / sizeof(s_info.history[0]));
1081
1082         return s_info.history[idx];
1083 }
1084
1085 static inline void do_command(const char *cmd)
1086 {
1087         /* Skip the first spaces */
1088         while (*cmd && *cmd == ' ') cmd++;
1089
1090         if (strlen(cmd) && *cmd != '#') {
1091                 if (!strncasecmp(cmd, "exit", 4) || !strncasecmp(cmd, "quit", 4)) {
1092                         ecore_main_loop_quit();
1093                 } else if (!strncasecmp(cmd, "set ", 4)) {
1094                         if (do_set(cmd) == 0)
1095                                 return;
1096                 } else if (!strncasecmp(cmd, "stat ", 5)) {
1097                         do_stat(cmd);
1098                 } else if (!strncasecmp(cmd, "get ", 4)) {
1099                         if (do_get(cmd) == 0)
1100                                 return;
1101                 } else if (!strncasecmp(cmd, "ls", 2)) {
1102                         if (do_ls(cmd) == 0)
1103                                 return;
1104                 } else if (!strncasecmp(cmd, "cd", 2)) {
1105                         if (do_cd(cmd) == 0)
1106                                 return;
1107                 } else if (!strncasecmp(cmd, "rm", 2)) {
1108                         if (do_rm(cmd) == 0)
1109                                 return;
1110                 } else if (!strncasecmp(cmd, "sh ", 3)) {
1111                         do_sh(cmd);
1112                 } else if (!strncasecmp(cmd, "x ", 2)) {
1113                         do_x(cmd);
1114                 } else {
1115                         help();
1116                 }
1117         }
1118
1119         prompt(NULL);
1120         return;
1121 }
1122
1123 static Eina_Bool input_cb(void *data, Ecore_Fd_Handler *fd_handler)
1124 {
1125         static int idx = 0;
1126         static char cmd_buffer[256];
1127         char ch;
1128         int fd;
1129         int ret;
1130         const char escape_str[] = { 0x1b, 0x5b, 0x0 };
1131         const char *escape_ptr = escape_str;
1132         const char *tmp;
1133
1134         if (fd_handler) {
1135                 fd = ecore_main_fd_handler_fd_get(fd_handler);
1136                 if (fd < 0) {
1137                         printf("FD is not valid: %d\n", fd);
1138                         return ECORE_CALLBACK_CANCEL;
1139                 }
1140         } else {
1141                 fd = s_info.input_fd;
1142         }
1143
1144         /*!
1145          * \note
1146          * Using this routine, we can implement the command recommend algorithm.
1147          * When a few more characters are matched with history of command, we can show it to user
1148          * Then the user will choose one or write new command
1149          */
1150
1151         /* Silly.. Silly */
1152         while ((ret = read(fd, &ch, sizeof(ch))) == sizeof(ch)) {
1153                 if (*escape_ptr == '\0') {
1154                         /* Function key */
1155                         switch (ch) {
1156                         case 0x41: /* UP */
1157                                 printf("%s2K%s1G", escape_str, escape_str);
1158                                 tmp = get_command(--s_info.history_idx);
1159                                 if (!tmp) {
1160                                         s_info.history_idx = 0;
1161                                         cmd_buffer[0] = '\0';
1162                                         prompt(NULL);
1163                                 } else {
1164                                         strcpy(cmd_buffer, tmp);
1165                                         idx = strlen(cmd_buffer);
1166                                         prompt(cmd_buffer);
1167                                 }
1168                                 break;
1169                         case 0x42: /* DOWN */
1170                                 if (s_info.history_idx >= 0)
1171                                         break;
1172
1173                                 printf("%s2K%s1G", escape_str, escape_str);
1174                                 tmp = get_command(++s_info.history_idx);
1175                                 if (s_info.history_idx == 0) {
1176                                         s_info.history_idx = 0;
1177                                         cmd_buffer[0] = '\0';
1178                                         prompt(NULL);
1179                                 } else {
1180                                         strcpy(cmd_buffer, tmp);
1181                                         idx = strlen(cmd_buffer);
1182                                         prompt(cmd_buffer);
1183                                 }
1184                                 break;
1185                         case 0x43: /* RIGHT */
1186                                 break;
1187                         case 0x44: /* LEFT */
1188                                 break;
1189                         default:
1190                                 break;
1191                         }
1192
1193                         escape_ptr = escape_str;
1194                         continue;
1195                 } else if (ch == *escape_ptr) {
1196                         escape_ptr++;
1197                         continue;
1198                 }
1199
1200                 switch (ch) {
1201                 case 0x08: /* BKSP */
1202                         cmd_buffer[idx] = '\0';
1203                         if (idx > 0) {
1204                                 idx--;
1205                                 cmd_buffer[idx] = ' ';
1206                                 putc('\r', stdout);
1207                                 prompt(cmd_buffer);
1208                         }
1209
1210                         cmd_buffer[idx] = '\0';
1211                         putc('\r', stdout);
1212                         prompt(cmd_buffer);
1213                         break;
1214                 case 0x09: /* TAB */
1215                         if (!s_info.quick_search_node) {
1216                                 s_info.quick_search_node = node_child(s_info.curdir);
1217                                 s_info.quick_idx = idx;
1218                         } else {
1219                                 s_info.quick_search_node = node_next_sibling(s_info.quick_search_node);
1220                                 idx = s_info.quick_idx;
1221                         }
1222
1223                         if (!s_info.quick_search_node)
1224                                 break;
1225
1226                         printf("%s2K%s1G", escape_str, escape_str);
1227                         strcpy(cmd_buffer + idx, node_name(s_info.quick_search_node));
1228                         idx += strlen(node_name(s_info.quick_search_node));
1229                         prompt(cmd_buffer);
1230                         break;
1231                 case '\n':
1232                 case '\r':
1233                         cmd_buffer[idx] = '\0';
1234                         idx = 0;
1235                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
1236                                 putc((int)'\n', stdout);
1237                         do_command(cmd_buffer);
1238                         put_command(cmd_buffer);
1239                         memset(cmd_buffer, 0, sizeof(cmd_buffer));
1240                         s_info.history_idx = 0;
1241                         s_info.quick_search_node = NULL;
1242
1243                         /* Make a main loop processing for command handling */
1244                         return ECORE_CALLBACK_RENEW;
1245                 default:
1246                         cmd_buffer[idx++] = ch;
1247
1248                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
1249                                 putc((int)ch, stdout);
1250
1251                         if (idx == sizeof(cmd_buffer) - 1) {
1252                                 cmd_buffer[idx] = '\0';
1253                                 printf("\nCommand buffer is overflow: %s\n", cmd_buffer);
1254                                 idx = 0;
1255                         }
1256                         break;
1257                 }
1258         }
1259
1260         if (ret < 0 && !fd_handler)
1261                 ecore_main_loop_quit();
1262
1263         return ECORE_CALLBACK_RENEW;
1264 }
1265
1266 static void processing_line_buffer(const char *buffer)
1267 {
1268         int pid;
1269         char slavename[256];
1270         char pkgname[256];
1271         char abi[256];
1272         char inst_id[4096];
1273         char cluster[256];
1274         char category[256];
1275         char state[10];
1276         int refcnt;
1277         int fault_count;
1278         int list_count;
1279         int loaded_inst;
1280         int loaded_pkg;
1281         double ttl;
1282         int secured;
1283         double period;
1284         int width;
1285         int height;
1286         struct node *node;
1287         struct package *pkginfo;
1288         struct instance *instinfo;
1289         struct slave *slaveinfo;
1290         int i;
1291
1292         switch (s_info.cmd) {
1293         case PKG_LIST:
1294                 if (sscanf(buffer, "%d %255[^ ] %255[^ ] %255[^ ] %d %d %d", &pid, slavename, pkgname, abi, &refcnt, &fault_count, &list_count) != 7) {
1295                         printf("Invalid format : [%s]\n", buffer);
1296                         return;
1297                 }
1298
1299                 node = node_find(s_info.targetdir, pkgname);
1300                 if (!node) {
1301                         pkginfo = calloc(1, sizeof(*pkginfo));
1302                         if (!pkginfo) {
1303                                 printf("Error: %s\n", strerror(errno));
1304                                 return;
1305                         }
1306
1307                         pkginfo->pkgid = strdup("conf.file");
1308                         if (!pkginfo->pkgid)
1309                                 printf("Error: %s\n", strerror(errno));
1310
1311                         pkginfo->primary = 1;
1312
1313                         node = node_create(s_info.targetdir, pkgname, NODE_DIR);
1314                         if (!node) {
1315                                 free(pkginfo->pkgid);
1316                                 free(pkginfo);
1317                                 printf("Failed to create a new node (%s)\n", pkgname);
1318                                 return;
1319                         }
1320
1321                         node_set_mode(node, NODE_READ | NODE_EXEC);
1322                         node_set_data(node, pkginfo);
1323                 } else {
1324                         pkginfo = node_data(node);
1325                         if (!pkginfo) {
1326                                 printf("Package info is inavlid\n");
1327                                 return;
1328                         }
1329
1330                         free(pkginfo->slavename);
1331                         free(pkginfo->abi);
1332
1333                         pkginfo->slavename = NULL;
1334                         pkginfo->abi = NULL;
1335                 }
1336
1337                 node_set_age(node, s_info.age);
1338
1339                 pkginfo->slavename = strdup(slavename);
1340                 if (!pkginfo->slavename)
1341                         printf("Error: %s\n", strerror(errno));
1342
1343                 pkginfo->abi = strdup(abi);
1344                 if (!pkginfo->abi)
1345                         printf("Error: %s\n", strerror(errno));
1346
1347                 pkginfo->pid = pid;
1348                 pkginfo->refcnt = refcnt;
1349                 pkginfo->fault_count = fault_count;
1350                 pkginfo->inst_count = list_count;
1351                 break;
1352         case SLAVE_LIST:
1353                 if (sscanf(buffer, "%d %[^ ] %[^ ] %[^ ] %d %d %d %[^ ] %d %d %lf", &pid, slavename, pkgname, abi, &secured, &refcnt, &fault_count, state, &loaded_inst, &loaded_pkg, &ttl) != 11) {
1354                         printf("Invalid format : [%s]\n", buffer);
1355                         return;
1356                 }
1357                 node = node_find(s_info.targetdir, slavename);
1358                 if (!node) {
1359                         slaveinfo = calloc(1, sizeof(*slaveinfo));
1360                         if (!slaveinfo) {
1361                                 printf("Error: %s\n", strerror(errno));
1362                                 return;
1363                         }
1364
1365                         node = node_create(s_info.targetdir, slavename, NODE_DIR);
1366                         if (!node) {
1367                                 free(slaveinfo);
1368                                 return;
1369                         }
1370
1371                         node_set_mode(node, NODE_READ | NODE_EXEC);
1372                         node_set_data(node, slaveinfo);
1373                 } else {
1374                         slaveinfo = node_data(node);
1375                 }
1376
1377                 node_set_age(node, s_info.age);
1378
1379                 free(slaveinfo->pkgname);
1380                 free(slaveinfo->abi);
1381                 free(slaveinfo->state);
1382
1383                 slaveinfo->pkgname = strdup(pkgname);
1384                 if (!slaveinfo->pkgname)
1385                         printf("Error: %s\n", strerror(errno));
1386
1387                 slaveinfo->abi = strdup(abi);
1388                 if (!slaveinfo->abi)
1389                         printf("Error: %s\n", strerror(errno));
1390
1391                 slaveinfo->state = strdup(state);
1392                 if (!slaveinfo->state)
1393                         printf("Error: %s\n", strerror(errno));
1394
1395                 slaveinfo->pid = pid;
1396                 slaveinfo->secured = secured;
1397                 slaveinfo->refcnt = refcnt;
1398                 slaveinfo->fault_count = fault_count;
1399                 slaveinfo->loaded_inst = loaded_inst;
1400                 slaveinfo->loaded_pkg = loaded_pkg;
1401                 slaveinfo->ttl = ttl;
1402                 break;
1403         case INST_LIST:
1404                 if (sscanf(buffer, "%[^ ] %[^ ] %[^ ] %lf %[^ ] %d %d", inst_id, cluster, category, &period, state, &width, &height) != 7) {
1405                         printf("Invalid format : [%s]\n", buffer);
1406                         return;
1407                 }
1408
1409                 for (i = strlen(inst_id); i > 0 && inst_id[i] != '/'; i--);
1410                 i += (inst_id[i] == '/');
1411
1412                 node = node_find(s_info.targetdir, inst_id + i);
1413                 if (!node) {
1414                         instinfo = calloc(1, sizeof(*instinfo));
1415                         if (!instinfo) {
1416                                 printf("Error: %s\n", strerror(errno));
1417                                 return;
1418                         }
1419
1420                         node = node_create(s_info.targetdir, inst_id + i, NODE_FILE);
1421                         if (!node) {
1422                                 free(instinfo);
1423                                 return;
1424                         }
1425
1426                         node_set_mode(node, NODE_READ | NODE_WRITE);
1427                         node_set_data(node, instinfo);
1428                 } else {
1429                         instinfo = node_data(node);
1430                 }
1431
1432                 node_set_age(node, s_info.age);
1433
1434                 free(instinfo->id);
1435                 free(instinfo->cluster);
1436                 free(instinfo->category);
1437                 free(instinfo->state);
1438
1439                 instinfo->id = strdup(inst_id);
1440                 if (!instinfo->id)
1441                         printf("Error: %s\n", strerror(errno));
1442
1443                 instinfo->cluster = strdup(cluster);
1444                 if (!instinfo->cluster)
1445                         printf("Error: %s\n", strerror(errno));
1446
1447                 instinfo->category = strdup(category);
1448                 if (!instinfo->category)
1449                         printf("Error: %s\n", strerror(errno));
1450
1451                 instinfo->state = strdup(state);
1452                 if (!instinfo->state)
1453                         printf("Error: %s\n", strerror(errno));
1454
1455                 instinfo->period = period;
1456                 instinfo->width = width;
1457                 instinfo->height = height;
1458                 break;
1459         case INST_CTRL:
1460                 sscanf(buffer, "%d", &i);
1461                 printf("%s\n", strerror(i));
1462                 printf("Result: %d\n", i);
1463                 break;
1464         case SLAVE_CTRL:
1465                 sscanf(buffer, "%d", &i);
1466                 printf("Result: %d\n", i);
1467                 break;
1468         case MASTER_CTRL:
1469                 sscanf(buffer, "%d", &i);
1470                 printf("Result: %d\n", i);
1471                 break;
1472         default:
1473                 break;
1474         }
1475 }
1476
1477 static inline void do_line_command(void)
1478 {
1479         switch (s_info.cmd) {
1480         case PKG_LIST:
1481                 ls();
1482                 break;
1483         case INST_LIST:
1484                 ls();
1485                 break;
1486         case SLAVE_LIST:
1487                 ls();
1488                 break;
1489         case INST_CTRL:
1490                 break;
1491         case SLAVE_CTRL:
1492                 break;
1493         case MASTER_CTRL:
1494                 break;
1495         default:
1496                 break;
1497         }
1498         prompt(NULL);
1499 }
1500
1501 static Eina_Bool read_cb(void *data, Ecore_Fd_Handler *fd_handler)
1502 {
1503         int fd;
1504         static char *line_buffer = NULL;
1505         static int line_index = 0;
1506         static int bufsz = 256;
1507         char ch;
1508
1509         fd = ecore_main_fd_handler_fd_get(fd_handler);
1510         if (fd < 0) {
1511                 printf("FD is not valid: %d\n", fd);
1512                 return ECORE_CALLBACK_CANCEL;
1513         }
1514
1515         if (read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
1516                 printf("Error: %s\n", strerror(errno));
1517                 return ECORE_CALLBACK_CANCEL;
1518         }
1519
1520         if (!line_buffer) {
1521                 line_index = 0;
1522                 line_buffer = malloc(bufsz);
1523                 if (!line_buffer) {
1524                         printf("Error: %s\n", strerror(errno));
1525                         return ECORE_CALLBACK_CANCEL;
1526                 }
1527         }       
1528
1529         if (ch == '\n') { /* End of a line */
1530                 if (line_index == bufsz - 1) {
1531                         char *new_buf;
1532                         new_buf = realloc(line_buffer, bufsz + 2);
1533                         if (!new_buf) {
1534                                 printf("Error: %s\n", strerror(errno));
1535                                 free(line_buffer);
1536                                 line_buffer = NULL;
1537                                 line_index = 0;
1538                                 bufsz = 256;
1539                                 return ECORE_CALLBACK_CANCEL;
1540                         }
1541
1542                         line_buffer = new_buf;
1543                 }
1544
1545                 line_buffer[line_index] = '\0';
1546
1547                 if (!strcmp(line_buffer, "EOD")) {
1548                         do_line_command();
1549                         s_info.cmd = NOP;
1550                 } else {
1551                         processing_line_buffer(line_buffer);
1552                 }
1553
1554                 free(line_buffer);
1555                 line_buffer = NULL;
1556                 line_index = 0;
1557                 bufsz = 256;
1558         } else {
1559                 char *new_buf;
1560
1561                 line_buffer[line_index++] = ch;
1562                 if (line_index == bufsz - 1) {
1563                         bufsz += 256;
1564                         new_buf = realloc(line_buffer, bufsz);
1565                         if (!new_buf) {
1566                                 printf("Error: %s\n", strerror(errno));
1567                                 free(line_buffer);
1568                                 line_buffer = NULL;
1569                                 line_index = 0;
1570                                 bufsz = 256;
1571                                 return ECORE_CALLBACK_CANCEL;
1572                         }
1573
1574                         line_buffer = new_buf;
1575                 }
1576         }
1577
1578         return ECORE_CALLBACK_RENEW;
1579 }
1580
1581 static int ret_cb(pid_t pid, int handle, const struct packet *packet, void *data)
1582 {
1583         const char *fifo_name;
1584         int ret;
1585
1586         if (packet_get(packet, "si", &fifo_name, &ret) != 2) {
1587                 printf("Invalid packet\n");
1588                 return -EFAULT;
1589         }
1590
1591         if (ret != 0) {
1592                 printf("Returns %d\n", ret);
1593                 return ret;
1594         }
1595
1596         printf("FIFO: %s\n", fifo_name);
1597
1598         s_info.fifo_handle = open(fifo_name, O_RDONLY | O_NONBLOCK);
1599         if (s_info.fifo_handle < 0) {
1600                 printf("Error: %s\n", strerror(errno));
1601                 s_info.fifo_handle = -EINVAL;
1602                 ecore_main_loop_quit();
1603                 return -EINVAL;
1604         }
1605
1606         s_info.fd_handler = ecore_main_fd_handler_add(s_info.fifo_handle, ECORE_FD_READ, read_cb, NULL, NULL, NULL);
1607         if (!s_info.fd_handler) {
1608                 printf("Failed to add a fd handler\n");
1609                 close(s_info.fifo_handle);
1610                 s_info.fifo_handle = -EINVAL;
1611                 ecore_main_loop_quit();
1612                 return -EFAULT;
1613         }
1614
1615         prompt(NULL);
1616
1617         if (s_info.input_fd == STDIN_FILENO) {
1618                 if (fcntl(s_info.input_fd, F_SETFL, O_NONBLOCK) < 0)
1619                         printf("Error: %s\n", strerror(errno));
1620
1621                 s_info.in_handler = ecore_main_fd_handler_add(s_info.input_fd, ECORE_FD_READ, input_cb, NULL, NULL, NULL);
1622                 if (!s_info.in_handler) {
1623                         printf("Failed to add a input handler\n");
1624                         ecore_main_loop_quit();
1625                         return -EFAULT;
1626                 }
1627         }
1628
1629         return 0;
1630 }
1631
1632 static int disconnected_cb(int handle, void *data)
1633 {
1634         printf("Disconnected\n");
1635         ecore_main_loop_quit();
1636         return 0;
1637 }
1638
1639 static int connected_cb(int handle, void *data)
1640 {
1641         struct packet *packet;
1642
1643         printf("Connected\n");
1644
1645         packet = packet_create("liveinfo_hello", "d", 0.0f);
1646         if (!packet) {
1647                 printf("Failed to build a packet for hello\n");
1648                 com_core_packet_client_fini(s_info.fd);
1649                 s_info.fd = -EINVAL;
1650                 return -EFAULT;
1651         }
1652
1653         s_info.fd = handle;
1654
1655         if (com_core_packet_async_send(s_info.fd, packet, 0.0f, ret_cb, NULL) < 0) {
1656                 printf("Failed to send a packet hello\n");
1657                 packet_destroy(packet);
1658                 com_core_packet_client_fini(s_info.fd);
1659                 s_info.fd = -EINVAL;
1660                 return -EFAULT;
1661         }
1662
1663         packet_destroy(packet);
1664         return 0;
1665 }
1666
1667 int main(int argc, char *argv[])
1668 {
1669         struct termios ttystate;
1670         static struct method s_table[] = {
1671                 {
1672                         .cmd = NULL,
1673                         .handler = NULL,
1674                 },
1675         };
1676         static struct option long_options[] = {
1677                 { "batchmode", required_argument, 0, 'b' },
1678                 { "help", no_argument, 0, 'h' },
1679                 { "verbose", required_argument, 0, 'v' },
1680                 { 0, 0, 0, 0 }
1681         };
1682         int option_index;
1683         int c;
1684
1685         do {
1686                 c = getopt_long(argc, argv, "b:hv:", long_options, &option_index);
1687                 switch (c) {
1688                 case 'b':
1689                         if (!optarg || !*optarg) {
1690                                 printf("Invalid argument\n");
1691                                 help();
1692                                 return -EINVAL;
1693                         }
1694
1695                         if (s_info.input_fd != STDIN_FILENO) {
1696                                 /* Close the previously, opened file */
1697                                 close(s_info.input_fd);
1698                         }
1699
1700                         s_info.input_fd = open(optarg, O_RDONLY);
1701                         if (s_info.input_fd < 0) {
1702                                 printf("Unable to access %s (%s)\n", optarg, strerror(errno));
1703                                 return -EIO;
1704                         }
1705                         break;
1706                 case 'h':
1707                         help();
1708                         return 0;
1709                 case 'v':
1710                         if (!optarg || !*optarg) {
1711                                 printf("Invalid argument\n");
1712                                 help();
1713                                 return -EINVAL;
1714                         }
1715
1716                         s_info.verbose = !strcmp(optarg, "true");
1717                         break;
1718                 default:
1719                         break;
1720                 }
1721         } while (c != -1);
1722
1723         ecore_init();
1724         g_type_init();
1725
1726         com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
1727         com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
1728         livebox_service_init();
1729
1730         s_info.fd = com_core_packet_client_init(SOCKET_FILE, 0, s_table);
1731         if (s_info.fd < 0) {
1732                 printf("Failed to make a connection\n");
1733                 return -EIO;
1734         }
1735
1736         if (s_info.input_fd == STDIN_FILENO) {
1737                 printf("Type your command on below empty line\n");
1738
1739                 if (tcgetattr(s_info.input_fd, &ttystate) < 0) {
1740                         printf("Error: %s\n", strerror(errno));
1741                 } else {
1742                         ttystate.c_lflag &= ~(ICANON | ECHO);
1743                         ttystate.c_cc[VMIN] = 1;
1744
1745                         if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1746                                 printf("Error: %s\n", strerror(errno));
1747                 }
1748         } else {
1749                 printf("Batch mode enabled\n");
1750         }
1751
1752         if (setvbuf(stdout, (char *)NULL, _IONBF, 0) != 0)
1753                 printf("Error: %s\n", strerror(errno));
1754
1755         init_directory();
1756
1757         ecore_main_loop_begin();
1758
1759         fini_directory();
1760         livebox_service_fini();
1761
1762         if (s_info.fd > 0) {
1763                 com_core_packet_client_fini(s_info.fd);
1764                 s_info.fd = -EINVAL;
1765         }
1766
1767         if (s_info.fd_handler) {
1768                 ecore_main_fd_handler_del(s_info.fd_handler);
1769                 s_info.fd_handler = NULL;
1770         }
1771
1772         if (s_info.input_fd == STDIN_FILENO) {
1773                 ttystate.c_lflag |= ICANON | ECHO;
1774                 if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1775                         printf("Error: %s\n", strerror(errno));
1776         } else {
1777                 close(s_info.input_fd);
1778         }
1779
1780         if (s_info.fifo_handle > 0) {
1781                 close(s_info.fifo_handle);
1782                 s_info.fifo_handle = -EINVAL;
1783         }
1784
1785         if (s_info.in_handler) {
1786                 ecore_main_fd_handler_del(s_info.in_handler);
1787                 s_info.in_handler = NULL;
1788         }
1789
1790         ecore_shutdown();
1791         putc((int)'\n', stdout);
1792         return 0;
1793 }
1794
1795 /* End of a file */