Various patches are applied
[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.1 (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://floralicense.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                 break;
647         case PROVIDER:
648                 printf("Not supported yet\n");
649                 break;
650         case PKG_INSTANCE:
651                 printf("Not supported yet\n");
652                 break;
653         case PROVIDER_INSTANCE:
654                 printf("Not supported yet\n");
655                 break;
656         case ROOT:
657                 printf("Not supported yet\n");
658                 break;
659         }
660
661         return 0;
662 }
663
664 static inline int do_set(const char *cmd)
665 {
666         int i;
667         char variable[4096] = { '0', };
668
669         cmd += 4;
670         i = get_token(cmd, variable);
671
672         cmd += i;
673         while (*cmd && *cmd == ' ') cmd++;
674
675         if (!i || !*cmd) {
676                 printf("Invalid argument(%s): set [VAR] [VAL]\n", cmd);
677                 return -EINVAL;
678         }
679
680         send_command("set", variable, cmd);
681         return 0;
682 }
683
684 static inline int do_get(const char *cmd)
685 {
686         cmd += 4;
687
688         while (*cmd && *cmd == ' ') cmd++;
689         if (!*cmd) {
690                 printf("Invalid argument(%s): get [VAR]\n", cmd);
691                 return -EINVAL;
692         }
693
694         send_command("get", cmd, "");
695         return 0;
696 }
697
698 static inline int do_ls(const char *cmd)
699 {
700         const char *name;
701         struct node *parent;
702
703         cmd += 2;
704
705         while (*cmd && *cmd == ' ')
706                 cmd++;
707
708         s_info.targetdir = *cmd ? update_target_dir(cmd) : s_info.curdir;
709         if (!s_info.targetdir) {
710                 printf("%s is not exists\n", cmd);
711                 return -ENOENT;
712         }
713
714         name = node_name(s_info.targetdir);
715         if (name) {
716                 if (!strcmp(name, "package")) {
717                         if (s_info.cmd == NOP) {
718                                 send_pkg_list();
719                                 return 0;
720                         }
721
722                         printf("Waiting the server response\n");
723                         return -EBUSY;
724                 } else if (!strcmp(name, "provider")) {
725                         if (s_info.cmd == NOP) {
726                                 send_slave_list();
727                                 return 0;
728                         }
729
730                         printf("Waiting the server response\n");
731                         return -EBUSY;
732                 }
733         }
734
735         parent = node_parent(s_info.targetdir);
736         if (parent && node_name(parent)) {
737                 if (!strcmp(node_name(parent), "package")) {
738                         if (s_info.cmd != NOP) {
739                                 printf("Waiting the server response\n");
740                                 return -EBUSY;
741                         }
742
743                         send_inst_list(name);
744                         return 0;
745                 }
746         }
747
748         ls();
749         return -1;
750 }
751
752 static inline int do_cd(const char *cmd)
753 {
754         cmd += 2;
755
756         while (*cmd && *cmd == ' ')
757                  cmd++;
758
759         if (!*cmd)
760                 return -1;
761
762         if (s_info.cmd != NOP) {
763                 printf("Waiting the server response\n");
764                 return -EBUSY;
765         }
766
767         s_info.targetdir = update_target_dir(cmd);
768         if (!s_info.targetdir) {
769                 printf("%s is not exists\n", cmd);
770                 return -ENOENT;
771         }
772
773         if (node_type(s_info.targetdir) != NODE_DIR) {
774                 printf("Unable change directory to %s\n", cmd);
775                 return -EINVAL;
776         }
777
778         if (!(node_mode(s_info.targetdir) & NODE_EXEC)) {
779                 printf("Access denied %s\n", cmd);
780                 return -EACCES;
781         }
782
783         s_info.curdir = s_info.targetdir;
784         return -1;
785 }
786
787 static inline int do_rm(const char *cmd)
788 {
789         cmd += 2;
790         while (*cmd && *cmd == ' ') cmd++;
791         if (!*cmd)
792                 return -1;
793
794         if (s_info.cmd != NOP) {
795                 printf("Waiting the server response\n");
796                 return -EBUSY;
797         }
798
799         s_info.targetdir = update_target_dir(cmd);
800         if (!s_info.targetdir) {
801                 printf("%s is not exists\n", cmd);
802                 return -ENOENT;
803         }
804
805         if (!(node_mode(s_info.targetdir) & NODE_WRITE)) {
806                 printf("Access denied %s\n", cmd);
807                 return -EACCES;
808         }
809
810         send_inst_delete();
811         return 0;
812 }
813
814 #if !defined(WCOREDUMP)
815 #define WCOREDUMP(a)    0
816 #endif
817
818 static inline void do_sh(const char *cmd)
819 {
820         pid_t pid;
821
822         cmd += 3;
823
824         while (*cmd && *cmd == ' ') cmd++;
825         if (!*cmd)
826                 return;
827
828         pid = fork();
829         if (pid == 0) {
830                 char command[256];
831                 int idx;
832                 idx = 0;
833
834                 while (idx < (sizeof(command) - 1) && *cmd && *cmd != ' ')
835                         command[idx++] = *cmd++;
836                 command[idx] = '\0';
837
838                 if (execl(command, cmd, NULL) < 0)
839                         printf("Failed to execute: %s\n", strerror(errno));
840
841                 exit(0);
842         } else if (pid < 0) {
843                 printf("Failed to create a new process: %s\n", strerror(errno));
844         } else {
845                 int status;
846                 if (waitpid(pid, &status, 0) < 0) {
847                         printf("error: %s\n", strerror(errno));
848                 } else {
849                         if (WIFEXITED(status)) {
850                                 printf("Exit: %d\n", WEXITSTATUS(status));
851                         } else if (WIFSIGNALED(status)) {
852                                 printf("Terminated by %d %s\n", WTERMSIG(status), WCOREDUMP(status) ? " - core generated" : "");
853                         } else if (WIFSTOPPED(status)) {
854                                 printf("Stopped by %d\n", WSTOPSIG(status));
855                         } else if (WIFCONTINUED(status)) {
856                                 printf("Child is resumed\n");
857                         }
858                 }
859         }
860 }
861
862 static inline int get_pixmap_size(Display *disp, Pixmap id, int *x, int *y, unsigned int *w, unsigned int *h)
863 {
864         Window dummy_win;
865         unsigned int dummy_border, dummy_depth;
866         int _x;
867         int _y;
868
869         if (!x)
870                 x = &_x;
871         if (!y)
872                 y = &_y;
873
874         if (!XGetGeometry(disp, id, &dummy_win, x, y, w, h, &dummy_border, &dummy_depth))
875                 return -EFAULT;
876
877         return 0;
878 }
879
880 static inline int do_capture(Display *disp, Pixmap id, const char *filename)
881 {
882         XShmSegmentInfo si;
883         XImage *xim;
884         Visual *visual;
885         unsigned int w;
886         unsigned int h;
887         int bufsz;
888         int fd;
889         Screen *screen;
890
891         screen = DefaultScreenOfDisplay(disp);
892         visual = DefaultVisualOfScreen(screen);
893
894         if (get_pixmap_size(disp, id, NULL, NULL, &w, &h) < 0) {
895                 printf("Failed to get size of a pixmap\n");
896                 return -EINVAL;
897         }
898
899         printf("Pixmap size: %dx%d\n", w, h);
900         bufsz = w * h * sizeof(int);
901
902         si.shmid = shmget(IPC_PRIVATE, bufsz, IPC_CREAT | 0666);
903         if (si.shmid < 0) {
904                 printf("shmget: %s\n", strerror(errno));
905                 return -EFAULT;
906         }
907
908         si.readOnly = False;
909         si.shmaddr = shmat(si.shmid, NULL, 0);
910         if (si.shmaddr == (void *)-1) {
911
912                 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
913                         printf("shmctl: %s\n", strerror(errno));
914
915                 return -EFAULT;
916         }
917
918         /*!
919          * \NOTE
920          * Use the 24 bits Pixmap for Video player
921          */
922         xim = XShmCreateImage(disp, visual, 24 /* (depth << 3) */, ZPixmap, NULL, &si, w, h);
923         if (xim == NULL) {
924                 if (shmdt(si.shmaddr) < 0)
925                         printf("shmdt: %s\n", strerror(errno));
926
927                 if (shmctl(si.shmid, IPC_RMID, 0) < 0)
928                         printf("shmctl: %s\n", strerror(errno));
929
930                 return -EFAULT;
931         }
932
933         xim->data = si.shmaddr;
934         XShmAttach(disp, &si);
935
936         XShmGetImage(disp, id, xim, 0, 0, 0xFFFFFFFF);
937         XSync(disp, False);
938
939         fd = open(filename, O_CREAT | O_RDWR, 0644);
940         if (fd >= 0) {
941                 if (write(fd, xim->data, bufsz) != bufsz)
942                         printf("Data is not fully written\n");
943
944                 close(fd);
945         } else {
946                 printf("Error: %sn\n", strerror(errno));
947         }
948
949         XShmDetach(disp, &si);
950         XDestroyImage(xim);
951
952         if (shmdt(si.shmaddr) < 0)
953                 printf("shmdt: %s\n", strerror(errno));
954
955         if (shmctl(si.shmid, IPC_RMID, 0) < 0)
956                 printf("shmctl: %s\n", strerror(errno));
957
958         return 0;
959 }
960
961 static inline void do_x(const char *cmd)
962 {
963         Display *disp;
964
965         cmd += 2;
966
967         while (*cmd && *cmd == ' ') cmd++;
968         if (!*cmd)
969                 return;
970
971         disp = XOpenDisplay(NULL);
972         if (!disp) {
973                 printf("Failed to connect to the X\n");
974                 return;
975         }
976
977         if (!strncasecmp(cmd, "damage ", 7)) {
978                 unsigned int winId;
979                 XRectangle rect;
980                 XserverRegion region;
981                 int x, y, w, h;
982
983                 cmd += 7;
984
985                 if (sscanf(cmd, "%u %d %d %d %d", &winId, &x, &y, &w, &h) != 5) {
986                         printf("Invalid argument\nx damage WINID_DEC X Y W H\n");
987                         return;
988                 }
989                 rect.x = x;
990                 rect.y = y;
991                 rect.width = w;
992                 rect.height = h;
993                 region = XFixesCreateRegion(disp, &rect, 1);
994                 XDamageAdd(disp, winId, region);
995                 XFixesDestroyRegion(disp, region);
996                 XFlush(disp);
997
998                 printf("Damage: %u %d %d %d %d\n", winId, x, y, w, h);
999         } else if (!strncasecmp(cmd, "capture ", 8)) {
1000                 unsigned int winId;
1001                 char filename[256];
1002
1003                 cmd += 8;
1004
1005                 if (sscanf(cmd, "%u %255[^ ]", &winId, filename) != 2) {
1006                         printf("Invalid argument\nx capture WINID_DEC FILENAME (%s)\n", cmd);
1007                         return;
1008                 }
1009                 if (do_capture(disp, winId, filename) == 0)
1010                         printf("Captured: %s\n", filename);
1011         } else if (!strncasecmp(cmd, "resize ", 7)) {
1012                 unsigned int winId;
1013                 int w;
1014                 int h;
1015
1016                 cmd += 7;
1017
1018                 if (sscanf(cmd, "%u %d %d", &winId, &w, &h) != 3) {
1019                         printf("Invalid argument\nx resize WINID_DEC W H\n");
1020                         return;
1021                 }
1022
1023                 XResizeWindow(disp, winId, w, h);
1024                 printf("Resize: %u %d %d\n", winId, w, h);
1025         } else if (!strncasecmp(cmd, "move ", 5)) {
1026                 unsigned int winId;
1027                 int x;
1028                 int y;
1029
1030                 cmd += 5;
1031                 if (sscanf(cmd, "%u %d %d", &winId, &x, &y) != 3) {
1032                         printf("Invalid argument\nx move WINID_DEC X Y\n");
1033                         return;
1034                 }
1035
1036                 XMoveWindow(disp, winId, x, y);
1037                 printf("Move: %u %d %d\n", winId, x, y);
1038         } else if (!strncasecmp(cmd, "map ", 4)) {
1039                 unsigned int winId;
1040                 cmd += 4;
1041                 if (sscanf(cmd, "%u", &winId) != 1) {
1042                         printf("Invalid argument\nx map WINID_DEC\n");
1043                         return;
1044                 }
1045                 XMapRaised(disp, winId);
1046                 printf("Map: %u\n", winId);
1047         } else if (!strncasecmp(cmd, "unmap ", 6)) {
1048                 unsigned int winId;
1049                 cmd += 6;
1050                 if (sscanf(cmd, "%u", &winId) != 1) {
1051                         printf("Invalid argument\nx unmap WINID_DEC\n");
1052                         return;
1053                 }
1054                 XUnmapWindow(disp, winId);
1055                 printf("Unmap: %u\n", winId);
1056         } else {
1057                 printf("Unknown command\n");
1058         }
1059
1060         XCloseDisplay(disp);
1061 }
1062
1063 static inline void put_command(const char *cmd)
1064 {
1065         if (s_info.history[s_info.history_top]) {
1066                 free(s_info.history[s_info.history_top]);
1067                 s_info.history[s_info.history_top] = NULL;
1068         }
1069
1070         s_info.history[s_info.history_top] = strdup(cmd);
1071         s_info.history_top = (s_info.history_top + !!s_info.history[s_info.history_top]) % (sizeof(s_info.history) / sizeof(s_info.history[0]));
1072 }
1073
1074 static inline const char *get_command(int idx)
1075 {
1076         idx = s_info.history_top + idx;
1077         while (idx < 0)
1078                 idx += (sizeof(s_info.history) / sizeof(s_info.history[0]));
1079
1080         return s_info.history[idx];
1081 }
1082
1083 static inline void do_command(const char *cmd)
1084 {
1085         /* Skip the first spaces */
1086         while (*cmd && *cmd == ' ') cmd++;
1087
1088         if (strlen(cmd) && *cmd != '#') {
1089                 if (!strncasecmp(cmd, "exit", 4) || !strncasecmp(cmd, "quit", 4)) {
1090                         ecore_main_loop_quit();
1091                 } else if (!strncasecmp(cmd, "set ", 4)) {
1092                         if (do_set(cmd) == 0)
1093                                 return;
1094                 } else if (!strncasecmp(cmd, "stat ", 5)) {
1095                         do_stat(cmd);
1096                 } else if (!strncasecmp(cmd, "get ", 4)) {
1097                         if (do_get(cmd) == 0)
1098                                 return;
1099                 } else if (!strncasecmp(cmd, "ls", 2)) {
1100                         if (do_ls(cmd) == 0)
1101                                 return;
1102                 } else if (!strncasecmp(cmd, "cd", 2)) {
1103                         if (do_cd(cmd) == 0)
1104                                 return;
1105                 } else if (!strncasecmp(cmd, "rm", 2)) {
1106                         if (do_rm(cmd) == 0)
1107                                 return;
1108                 } else if (!strncasecmp(cmd, "sh ", 3)) {
1109                         do_sh(cmd);
1110                 } else if (!strncasecmp(cmd, "x ", 2)) {
1111                         do_x(cmd);
1112                 } else {
1113                         help();
1114                 }
1115         }
1116
1117         prompt(NULL);
1118         return;
1119 }
1120
1121 static Eina_Bool input_cb(void *data, Ecore_Fd_Handler *fd_handler)
1122 {
1123         static int idx = 0;
1124         static char cmd_buffer[256];
1125         char ch;
1126         int fd;
1127         int ret;
1128         const char escape_str[] = { 0x1b, 0x5b, 0x0 };
1129         const char *escape_ptr = escape_str;
1130         const char *tmp;
1131
1132         if (fd_handler) {
1133                 fd = ecore_main_fd_handler_fd_get(fd_handler);
1134                 if (fd < 0) {
1135                         printf("FD is not valid: %d\n", fd);
1136                         return ECORE_CALLBACK_CANCEL;
1137                 }
1138         } else {
1139                 fd = s_info.input_fd;
1140         }
1141
1142         /*!
1143          * \note
1144          * Using this routine, we can implement the command recommend algorithm.
1145          * When a few more characters are matched with history of command, we can show it to user
1146          * Then the user will choose one or write new command
1147          */
1148
1149         /* Silly.. Silly */
1150         while ((ret = read(fd, &ch, sizeof(ch))) == sizeof(ch)) {
1151                 if (*escape_ptr == '\0') {
1152                         /* Function key */
1153                         switch (ch) {
1154                         case 0x41: /* UP */
1155                                 printf("%s2K%s1G", escape_str, escape_str);
1156                                 tmp = get_command(--s_info.history_idx);
1157                                 if (!tmp) {
1158                                         s_info.history_idx = 0;
1159                                         cmd_buffer[0] = '\0';
1160                                         prompt(NULL);
1161                                 } else {
1162                                         strcpy(cmd_buffer, tmp);
1163                                         idx = strlen(cmd_buffer);
1164                                         prompt(cmd_buffer);
1165                                 }
1166                                 break;
1167                         case 0x42: /* DOWN */
1168                                 if (s_info.history_idx >= 0)
1169                                         break;
1170
1171                                 printf("%s2K%s1G", escape_str, escape_str);
1172                                 tmp = get_command(++s_info.history_idx);
1173                                 if (s_info.history_idx == 0) {
1174                                         s_info.history_idx = 0;
1175                                         cmd_buffer[0] = '\0';
1176                                         prompt(NULL);
1177                                 } else {
1178                                         strcpy(cmd_buffer, tmp);
1179                                         idx = strlen(cmd_buffer);
1180                                         prompt(cmd_buffer);
1181                                 }
1182                                 break;
1183                         case 0x43: /* RIGHT */
1184                                 break;
1185                         case 0x44: /* LEFT */
1186                                 break;
1187                         default:
1188                                 break;
1189                         }
1190
1191                         escape_ptr = escape_str;
1192                         continue;
1193                 } else if (ch == *escape_ptr) {
1194                         escape_ptr++;
1195                         continue;
1196                 }
1197
1198                 switch (ch) {
1199                 case 0x08: /* BKSP */
1200                         cmd_buffer[idx] = '\0';
1201                         if (idx > 0) {
1202                                 idx--;
1203                                 cmd_buffer[idx] = ' ';
1204                                 putc('\r', stdout);
1205                                 prompt(cmd_buffer);
1206                         }
1207
1208                         cmd_buffer[idx] = '\0';
1209                         putc('\r', stdout);
1210                         prompt(cmd_buffer);
1211                         break;
1212                 case 0x09: /* TAB */
1213                         if (!s_info.quick_search_node) {
1214                                 s_info.quick_search_node = node_child(s_info.curdir);
1215                                 s_info.quick_idx = idx;
1216                         } else {
1217                                 s_info.quick_search_node = node_next_sibling(s_info.quick_search_node);
1218                                 idx = s_info.quick_idx;
1219                         }
1220
1221                         if (!s_info.quick_search_node)
1222                                 break;
1223
1224                         printf("%s2K%s1G", escape_str, escape_str);
1225                         strcpy(cmd_buffer + idx, node_name(s_info.quick_search_node));
1226                         idx += strlen(node_name(s_info.quick_search_node));
1227                         prompt(cmd_buffer);
1228                         break;
1229                 case '\n':
1230                 case '\r':
1231                         cmd_buffer[idx] = '\0';
1232                         idx = 0;
1233                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
1234                                 putc((int)'\n', stdout);
1235                         do_command(cmd_buffer);
1236                         put_command(cmd_buffer);
1237                         memset(cmd_buffer, 0, sizeof(cmd_buffer));
1238                         s_info.history_idx = 0;
1239                         s_info.quick_search_node = NULL;
1240
1241                         /* Make a main loop processing for command handling */
1242                         return ECORE_CALLBACK_RENEW;
1243                 default:
1244                         cmd_buffer[idx++] = ch;
1245
1246                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
1247                                 putc((int)ch, stdout);
1248
1249                         if (idx == sizeof(cmd_buffer) - 1) {
1250                                 cmd_buffer[idx] = '\0';
1251                                 printf("\nCommand buffer is overflow: %s\n", cmd_buffer);
1252                                 idx = 0;
1253                         }
1254                         break;
1255                 }
1256         }
1257
1258         if (ret < 0 && !fd_handler)
1259                 ecore_main_loop_quit();
1260
1261         return ECORE_CALLBACK_RENEW;
1262 }
1263
1264 static void processing_line_buffer(const char *buffer)
1265 {
1266         int pid;
1267         char slavename[256];
1268         char pkgname[256];
1269         char abi[256];
1270         char inst_id[4096];
1271         char cluster[256];
1272         char category[256];
1273         char state[10];
1274         int refcnt;
1275         int fault_count;
1276         int list_count;
1277         int loaded_inst;
1278         int loaded_pkg;
1279         double ttl;
1280         int secured;
1281         double period;
1282         int width;
1283         int height;
1284         struct node *node;
1285         struct package *pkginfo;
1286         struct instance *instinfo;
1287         struct slave *slaveinfo;
1288         int i;
1289
1290         switch (s_info.cmd) {
1291         case PKG_LIST:
1292                 if (sscanf(buffer, "%d %255[^ ] %255[^ ] %255[^ ] %d %d %d", &pid, slavename, pkgname, abi, &refcnt, &fault_count, &list_count) != 7) {
1293                         printf("Invalid format : [%s]\n", buffer);
1294                         return;
1295                 }
1296
1297                 node = node_find(s_info.targetdir, pkgname);
1298                 if (!node) {
1299                         pkginfo = calloc(1, sizeof(*pkginfo));
1300                         if (!pkginfo) {
1301                                 printf("Error: %s\n", strerror(errno));
1302                                 return;
1303                         }
1304
1305                         pkginfo->pkgid = strdup("conf.file");
1306                         if (!pkginfo->pkgid)
1307                                 printf("Error: %s\n", strerror(errno));
1308
1309                         pkginfo->primary = 1;
1310
1311                         node = node_create(s_info.targetdir, pkgname, NODE_DIR);
1312                         if (!node) {
1313                                 free(pkginfo->pkgid);
1314                                 free(pkginfo);
1315                                 printf("Failed to create a new node (%s)\n", pkgname);
1316                                 return;
1317                         }
1318
1319                         node_set_mode(node, NODE_READ | NODE_EXEC);
1320                         node_set_data(node, pkginfo);
1321                 } else {
1322                         pkginfo = node_data(node);
1323                         if (!pkginfo) {
1324                                 printf("Package info is inavlid\n");
1325                                 return;
1326                         }
1327
1328                         free(pkginfo->slavename);
1329                         free(pkginfo->abi);
1330
1331                         pkginfo->slavename = NULL;
1332                         pkginfo->abi = NULL;
1333                 }
1334
1335                 node_set_age(node, s_info.age);
1336
1337                 pkginfo->slavename = strdup(slavename);
1338                 if (!pkginfo->slavename)
1339                         printf("Error: %s\n", strerror(errno));
1340
1341                 pkginfo->abi = strdup(abi);
1342                 if (!pkginfo->abi)
1343                         printf("Error: %s\n", strerror(errno));
1344
1345                 pkginfo->pid = pid;
1346                 pkginfo->refcnt = refcnt;
1347                 pkginfo->fault_count = fault_count;
1348                 pkginfo->inst_count = list_count;
1349                 break;
1350         case SLAVE_LIST:
1351                 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) {
1352                         printf("Invalid format : [%s]\n", buffer);
1353                         return;
1354                 }
1355                 node = node_find(s_info.targetdir, slavename);
1356                 if (!node) {
1357                         slaveinfo = calloc(1, sizeof(*slaveinfo));
1358                         if (!slaveinfo) {
1359                                 printf("Error: %s\n", strerror(errno));
1360                                 return;
1361                         }
1362
1363                         node = node_create(s_info.targetdir, slavename, NODE_DIR);
1364                         if (!node) {
1365                                 free(slaveinfo);
1366                                 return;
1367                         }
1368
1369                         node_set_mode(node, NODE_READ | NODE_EXEC);
1370                         node_set_data(node, slaveinfo);
1371                 } else {
1372                         slaveinfo = node_data(node);
1373                 }
1374
1375                 node_set_age(node, s_info.age);
1376
1377                 free(slaveinfo->pkgname);
1378                 free(slaveinfo->abi);
1379                 free(slaveinfo->state);
1380
1381                 slaveinfo->pkgname = strdup(pkgname);
1382                 if (!slaveinfo->pkgname)
1383                         printf("Error: %s\n", strerror(errno));
1384
1385                 slaveinfo->abi = strdup(abi);
1386                 if (!slaveinfo->abi)
1387                         printf("Error: %s\n", strerror(errno));
1388
1389                 slaveinfo->state = strdup(state);
1390                 if (!slaveinfo->state)
1391                         printf("Error: %s\n", strerror(errno));
1392
1393                 slaveinfo->pid = pid;
1394                 slaveinfo->secured = secured;
1395                 slaveinfo->refcnt = refcnt;
1396                 slaveinfo->fault_count = fault_count;
1397                 slaveinfo->loaded_inst = loaded_inst;
1398                 slaveinfo->loaded_pkg = loaded_pkg;
1399                 slaveinfo->ttl = ttl;
1400                 break;
1401         case INST_LIST:
1402                 if (sscanf(buffer, "%[^ ] %[^ ] %[^ ] %lf %[^ ] %d %d", inst_id, cluster, category, &period, state, &width, &height) != 7) {
1403                         printf("Invalid format : [%s]\n", buffer);
1404                         return;
1405                 }
1406
1407                 for (i = strlen(inst_id); i > 0 && inst_id[i] != '/'; i--);
1408                 i += (inst_id[i] == '/');
1409
1410                 node = node_find(s_info.targetdir, inst_id + i);
1411                 if (!node) {
1412                         instinfo = calloc(1, sizeof(*instinfo));
1413                         if (!instinfo) {
1414                                 printf("Error: %s\n", strerror(errno));
1415                                 return;
1416                         }
1417
1418                         node = node_create(s_info.targetdir, inst_id + i, NODE_FILE);
1419                         if (!node) {
1420                                 free(instinfo);
1421                                 return;
1422                         }
1423
1424                         node_set_mode(node, NODE_READ | NODE_WRITE);
1425                         node_set_data(node, instinfo);
1426                 } else {
1427                         instinfo = node_data(node);
1428                 }
1429
1430                 node_set_age(node, s_info.age);
1431
1432                 free(instinfo->id);
1433                 free(instinfo->cluster);
1434                 free(instinfo->category);
1435                 free(instinfo->state);
1436
1437                 instinfo->id = strdup(inst_id);
1438                 if (!instinfo->id)
1439                         printf("Error: %s\n", strerror(errno));
1440
1441                 instinfo->cluster = strdup(cluster);
1442                 if (!instinfo->cluster)
1443                         printf("Error: %s\n", strerror(errno));
1444
1445                 instinfo->category = strdup(category);
1446                 if (!instinfo->category)
1447                         printf("Error: %s\n", strerror(errno));
1448
1449                 instinfo->state = strdup(state);
1450                 if (!instinfo->state)
1451                         printf("Error: %s\n", strerror(errno));
1452
1453                 instinfo->period = period;
1454                 instinfo->width = width;
1455                 instinfo->height = height;
1456                 break;
1457         case INST_CTRL:
1458                 sscanf(buffer, "%d", &i);
1459                 printf("%s\n", strerror(i));
1460                 printf("Result: %d\n", i);
1461                 break;
1462         case SLAVE_CTRL:
1463                 sscanf(buffer, "%d", &i);
1464                 printf("Result: %d\n", i);
1465                 break;
1466         case MASTER_CTRL:
1467                 sscanf(buffer, "%d", &i);
1468                 printf("Result: %d\n", i);
1469                 break;
1470         default:
1471                 break;
1472         }
1473 }
1474
1475 static inline void do_line_command(void)
1476 {
1477         switch (s_info.cmd) {
1478         case PKG_LIST:
1479                 ls();
1480                 break;
1481         case INST_LIST:
1482                 ls();
1483                 break;
1484         case SLAVE_LIST:
1485                 ls();
1486                 break;
1487         case INST_CTRL:
1488                 break;
1489         case SLAVE_CTRL:
1490                 break;
1491         case MASTER_CTRL:
1492                 break;
1493         default:
1494                 break;
1495         }
1496         prompt(NULL);
1497 }
1498
1499 static Eina_Bool read_cb(void *data, Ecore_Fd_Handler *fd_handler)
1500 {
1501         int fd;
1502         static char *line_buffer = NULL;
1503         static int line_index = 0;
1504         static int bufsz = 256;
1505         char ch;
1506
1507         fd = ecore_main_fd_handler_fd_get(fd_handler);
1508         if (fd < 0) {
1509                 printf("FD is not valid: %d\n", fd);
1510                 return ECORE_CALLBACK_CANCEL;
1511         }
1512
1513         if (read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
1514                 printf("Error: %s\n", strerror(errno));
1515                 return ECORE_CALLBACK_CANCEL;
1516         }
1517
1518         if (!line_buffer) {
1519                 line_index = 0;
1520                 line_buffer = malloc(bufsz);
1521                 if (!line_buffer) {
1522                         printf("Error: %s\n", strerror(errno));
1523                         return ECORE_CALLBACK_CANCEL;
1524                 }
1525         }       
1526
1527         if (ch == '\n') { /* End of a line */
1528                 if (line_index == bufsz - 1) {
1529                         char *new_buf;
1530                         new_buf = realloc(line_buffer, bufsz + 2);
1531                         if (!new_buf) {
1532                                 printf("Error: %s\n", strerror(errno));
1533                                 free(line_buffer);
1534                                 line_buffer = NULL;
1535                                 line_index = 0;
1536                                 bufsz = 256;
1537                                 return ECORE_CALLBACK_CANCEL;
1538                         }
1539
1540                         line_buffer = new_buf;
1541                 }
1542
1543                 line_buffer[line_index] = '\0';
1544
1545                 if (!strcmp(line_buffer, "EOD")) {
1546                         do_line_command();
1547                         s_info.cmd = NOP;
1548                 } else {
1549                         processing_line_buffer(line_buffer);
1550                 }
1551
1552                 free(line_buffer);
1553                 line_buffer = NULL;
1554                 line_index = 0;
1555                 bufsz = 256;
1556         } else {
1557                 char *new_buf;
1558
1559                 line_buffer[line_index++] = ch;
1560                 if (line_index == bufsz - 1) {
1561                         bufsz += 256;
1562                         new_buf = realloc(line_buffer, bufsz);
1563                         if (!new_buf) {
1564                                 printf("Error: %s\n", strerror(errno));
1565                                 free(line_buffer);
1566                                 line_buffer = NULL;
1567                                 line_index = 0;
1568                                 bufsz = 256;
1569                                 return ECORE_CALLBACK_CANCEL;
1570                         }
1571
1572                         line_buffer = new_buf;
1573                 }
1574         }
1575
1576         return ECORE_CALLBACK_RENEW;
1577 }
1578
1579 static int ret_cb(pid_t pid, int handle, const struct packet *packet, void *data)
1580 {
1581         const char *fifo_name;
1582         int ret;
1583
1584         if (packet_get(packet, "si", &fifo_name, &ret) != 2) {
1585                 printf("Invalid packet\n");
1586                 return -EFAULT;
1587         }
1588
1589         if (ret != 0) {
1590                 printf("Returns %d\n", ret);
1591                 return ret;
1592         }
1593
1594         printf("FIFO: %s\n", fifo_name);
1595
1596         s_info.fifo_handle = open(fifo_name, O_RDONLY | O_NONBLOCK);
1597         if (s_info.fifo_handle < 0) {
1598                 printf("Error: %s\n", strerror(errno));
1599                 s_info.fifo_handle = -EINVAL;
1600                 ecore_main_loop_quit();
1601                 return -EINVAL;
1602         }
1603
1604         s_info.fd_handler = ecore_main_fd_handler_add(s_info.fifo_handle, ECORE_FD_READ, read_cb, NULL, NULL, NULL);
1605         if (!s_info.fd_handler) {
1606                 printf("Failed to add a fd handler\n");
1607                 close(s_info.fifo_handle);
1608                 s_info.fifo_handle = -EINVAL;
1609                 ecore_main_loop_quit();
1610                 return -EFAULT;
1611         }
1612
1613         prompt(NULL);
1614
1615         if (s_info.input_fd == STDIN_FILENO) {
1616                 if (fcntl(s_info.input_fd, F_SETFL, O_NONBLOCK) < 0)
1617                         printf("Error: %s\n", strerror(errno));
1618
1619                 s_info.in_handler = ecore_main_fd_handler_add(s_info.input_fd, ECORE_FD_READ, input_cb, NULL, NULL, NULL);
1620                 if (!s_info.in_handler) {
1621                         printf("Failed to add a input handler\n");
1622                         ecore_main_loop_quit();
1623                         return -EFAULT;
1624                 }
1625         }
1626
1627         return 0;
1628 }
1629
1630 static int disconnected_cb(int handle, void *data)
1631 {
1632         printf("Disconnected\n");
1633         ecore_main_loop_quit();
1634         return 0;
1635 }
1636
1637 static int connected_cb(int handle, void *data)
1638 {
1639         struct packet *packet;
1640
1641         printf("Connected\n");
1642
1643         packet = packet_create("liveinfo_hello", "d", 0.0f);
1644         if (!packet) {
1645                 printf("Failed to build a packet for hello\n");
1646                 com_core_packet_client_fini(s_info.fd);
1647                 s_info.fd = -EINVAL;
1648                 return -EFAULT;
1649         }
1650
1651         s_info.fd = handle;
1652
1653         if (com_core_packet_async_send(s_info.fd, packet, 0.0f, ret_cb, NULL) < 0) {
1654                 printf("Failed to send a packet hello\n");
1655                 packet_destroy(packet);
1656                 com_core_packet_client_fini(s_info.fd);
1657                 s_info.fd = -EINVAL;
1658                 return -EFAULT;
1659         }
1660
1661         packet_destroy(packet);
1662         return 0;
1663 }
1664
1665 int main(int argc, char *argv[])
1666 {
1667         struct termios ttystate;
1668         static struct method s_table[] = {
1669                 {
1670                         .cmd = NULL,
1671                         .handler = NULL,
1672                 },
1673         };
1674         static struct option long_options[] = {
1675                 { "batchmode", required_argument, 0, 'b' },
1676                 { "help", no_argument, 0, 'h' },
1677                 { "verbose", required_argument, 0, 'v' },
1678                 { 0, 0, 0, 0 }
1679         };
1680         int option_index;
1681         int c;
1682
1683         do {
1684                 c = getopt_long(argc, argv, "b:hv:", long_options, &option_index);
1685                 switch (c) {
1686                 case 'b':
1687                         if (!optarg || !*optarg) {
1688                                 printf("Invalid argument\n");
1689                                 help();
1690                                 return -EINVAL;
1691                         }
1692
1693                         if (s_info.input_fd != STDIN_FILENO) {
1694                                 /* Close the previously, opened file */
1695                                 close(s_info.input_fd);
1696                         }
1697
1698                         s_info.input_fd = open(optarg, O_RDONLY);
1699                         if (s_info.input_fd < 0) {
1700                                 printf("Unable to access %s (%s)\n", optarg, strerror(errno));
1701                                 return -EIO;
1702                         }
1703                         break;
1704                 case 'h':
1705                         help();
1706                         return 0;
1707                 case 'v':
1708                         if (!optarg || !*optarg) {
1709                                 printf("Invalid argument\n");
1710                                 help();
1711                                 return -EINVAL;
1712                         }
1713
1714                         s_info.verbose = !strcmp(optarg, "true");
1715                         break;
1716                 default:
1717                         break;
1718                 }
1719         } while (c != -1);
1720
1721         ecore_init();
1722         g_type_init();
1723
1724         com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
1725         com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
1726         livebox_service_init();
1727
1728         s_info.fd = com_core_packet_client_init(SOCKET_FILE, 0, s_table);
1729         if (s_info.fd < 0) {
1730                 printf("Failed to make a connection\n");
1731                 return -EIO;
1732         }
1733
1734         if (s_info.input_fd == STDIN_FILENO) {
1735                 printf("Type your command on below empty line\n");
1736
1737                 if (tcgetattr(s_info.input_fd, &ttystate) < 0) {
1738                         printf("Error: %s\n", strerror(errno));
1739                 } else {
1740                         ttystate.c_lflag &= ~(ICANON | ECHO);
1741                         ttystate.c_cc[VMIN] = 1;
1742
1743                         if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1744                                 printf("Error: %s\n", strerror(errno));
1745                 }
1746         } else {
1747                 printf("Batch mode enabled\n");
1748         }
1749
1750         if (setvbuf(stdout, (char *)NULL, _IONBF, 0) != 0)
1751                 printf("Error: %s\n", strerror(errno));
1752
1753         init_directory();
1754
1755         ecore_main_loop_begin();
1756
1757         fini_directory();
1758         livebox_service_fini();
1759
1760         if (s_info.fd > 0) {
1761                 com_core_packet_client_fini(s_info.fd);
1762                 s_info.fd = -EINVAL;
1763         }
1764
1765         if (s_info.fd_handler) {
1766                 ecore_main_fd_handler_del(s_info.fd_handler);
1767                 s_info.fd_handler = NULL;
1768         }
1769
1770         if (s_info.input_fd == STDIN_FILENO) {
1771                 ttystate.c_lflag |= ICANON | ECHO;
1772                 if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1773                         printf("Error: %s\n", strerror(errno));
1774         } else {
1775                 close(s_info.input_fd);
1776         }
1777
1778         if (s_info.fifo_handle > 0) {
1779                 close(s_info.fifo_handle);
1780                 s_info.fifo_handle = -EINVAL;
1781         }
1782
1783         if (s_info.in_handler) {
1784                 ecore_main_fd_handler_del(s_info.in_handler);
1785                 s_info.in_handler = NULL;
1786         }
1787
1788         ecore_shutdown();
1789         putc((int)'\n', stdout);
1790         return 0;
1791 }
1792
1793 /* End of a file */