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