Update the liveinfo.
[apps/livebox/data-provider-master.git] / util_liveinfo / src / liveinfo.c
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <unistd.h>
19 #include <getopt.h>
20 #include <errno.h>
21 #include <libgen.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <termios.h>
26
27 #include <glib.h>
28 #include <glib-object.h>
29
30 #include <packet.h>
31 #include <com-core_packet.h>
32 #include <com-core.h>
33
34 #include <livebox-service.h>
35
36 #include <Ecore.h>
37
38 #include "liveinfo.h"
39 #include "node.h"
40
41 #define PROMPT "liveinfo "
42
43 struct package {
44         int primary;
45         char *pkgid;
46
47         int pid;
48         char *slavename;
49         char *abi;
50         int refcnt;
51         int fault_count;
52         int inst_count;
53 };
54
55 struct instance {
56         char *id;
57         char *cluster;
58         char *category;
59         double period;
60         char *state;
61         int width;
62         int height;
63 };
64
65 struct slave {
66         int pid;
67         char *pkgname;
68         char *abi;
69         int secured;
70         int refcnt;
71         int fault_count;
72         char *state;
73         int loaded_inst;
74         int loaded_pkg;
75         double ttl;
76 };
77
78 enum command {
79         NOP,
80         PKG_LIST,
81         INST_LIST,
82         SLAVE_LIST,     
83         INST_CTRL,
84         SLAVE_CTRL,
85         MASTER_CTRL,
86 };
87
88 static struct info {
89         int fifo_handle;
90         int fd;
91         Ecore_Fd_Handler *fd_handler;
92         Ecore_Fd_Handler *in_handler;
93
94         struct node *rootdir;
95         struct node *curdir;
96         struct node *targetdir;
97
98         enum command cmd;
99
100         int input_fd;
101         int verbose;
102
103         int age;
104 } s_info = {
105         .fifo_handle = -EINVAL,
106         .fd = -EINVAL,
107         .fd_handler = NULL,
108         .in_handler = NULL,
109         .rootdir = NULL,
110         .curdir = NULL,
111         .targetdir = NULL,
112         .cmd = NOP,
113         .input_fd = STDIN_FILENO,
114         .verbose = 0,
115         .age = 0,
116 };
117
118 char *optarg;
119 int errno;
120 int optind;
121 int optopt;
122 int opterr;
123
124 static Eina_Bool input_cb(void *data, Ecore_Fd_Handler *fd_handler);
125
126 static Eina_Bool process_line_cb(void *data)
127 {
128         input_cb(NULL, NULL);
129         return ECORE_CALLBACK_CANCEL;
130 }
131
132 static inline void prompt(const char *cmdline)
133 {
134         char *path;
135
136         if (s_info.input_fd != STDIN_FILENO) {
137                 /* To prevent recursive call, add function to the main loop (idler) */
138                 ecore_idler_add(process_line_cb, NULL);
139                 return;
140         }
141
142         path = node_to_abspath(s_info.curdir);
143         printf(PROMPT"%s # %s", path, cmdline ? cmdline : "");
144         free(path);
145 }
146
147 static void provider_del_cb(struct node *node)
148 {
149         struct slave *info;
150
151         info = node_data(node);
152         if (!info)
153                 return;
154
155         free(info->pkgname);
156         free(info->abi);
157         free(info->state);
158         free(info);
159 }
160
161 static void package_del_cb(struct node *node)
162 {
163         struct package *info;
164
165         info = node_data(node);
166         if (!info)
167                 return;
168
169         free(info->pkgid);
170         free(info->slavename);
171         free(info->abi);
172         free(info);
173 }
174
175 static void inst_del_cb(struct node *node)
176 {
177         struct instance *info;
178
179         info = node_data(node);
180         if (!info)
181                 return;
182
183         free(info->id);
184         free(info->cluster);
185         free(info->category);
186         free(info->state);
187         free(info);
188 }
189
190 static inline void ls(void)
191 {
192         struct node *node;
193         int cnt = 0;
194         int is_package;
195         int is_provider;
196         int is_instance;
197         struct node *next_node;
198
199         if (!(node_mode(s_info.targetdir) & NODE_READ)) {
200                 printf("Access denied\n");
201                 return;
202         }
203
204         is_package = node_name(s_info.targetdir) && !strcmp(node_name(s_info.targetdir), "package");
205         is_provider = !is_package && node_name(s_info.targetdir) && !strcmp(node_name(s_info.targetdir), "provider");
206         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");
207
208         node = node_child(s_info.targetdir);
209         while (node) {
210                 if (is_package) {
211                         struct package *info;
212
213                         next_node = node_next_sibling(node);
214                         if (node_age(node) != s_info.age) {
215                                 node_delete(node, package_del_cb);
216                                 node = next_node;
217                                 continue;
218                         }
219
220                         info = node_data(node);
221                         printf(" %3d %20s %5s ", info->inst_count, info->slavename ? info->slavename : "(none)", info->abi ? info->abi : "?");
222                 } else if (is_provider) {
223                         struct slave *info;
224
225                         next_node = node_next_sibling(node);
226                         if (node_age(node) != s_info.age) {
227                                 node_delete(node, provider_del_cb);
228                                 node = next_node;
229                                 continue;
230                         }
231
232                         info = node_data(node);
233                         printf(" %3d %5s %5.2f ", info->loaded_inst, info->abi ? info->abi : "?", info->ttl);
234                 } else if (is_instance) {
235                         struct instance *info;
236                         struct stat stat;
237                         char buf[4096];
238
239                         next_node = node_next_sibling(node);
240
241                         if (node_age(node) != s_info.age) {
242                                 node_delete(node, inst_del_cb);
243                                 node = next_node;
244                                 continue;
245                         }
246
247                         info = node_data(node);
248
249                         printf(" %5.2f %6s %10s %10s %4dx%-4d ", info->period, info->state, info->cluster, info->category, info->width, info->height);
250                         snprintf(buf, sizeof(buf), "/opt/usr/share/live_magazine/reader/%s", node_name(node));
251                         if (lstat(buf, &stat) < 0)
252                                 printf("%3d ERR ", errno);
253                         else
254                                 printf("%2.2lf KB ", (double)stat.st_size / 1024.0f);
255                 }
256
257                 if (node_type(node) == NODE_DIR)
258                         printf("%s/", node_name(node));
259                 else if (node_type(node) == NODE_FILE)
260                         printf("%s", node_name(node));
261
262                 printf("\n");
263                 node = node_next_sibling(node);
264                 cnt++;
265         }
266
267         printf("Total: %d\n", cnt);
268 }
269
270 static void send_slave_list(void)
271 {
272         struct packet *packet;
273
274         if (s_info.cmd != NOP) {
275                 printf("Previous command is not finished\n");
276                 return;
277         }
278
279         packet = packet_create_noack("slave_list", "d", 0.0f);
280         if (!packet) {
281                 printf("Failed to create a packet\n");
282                 return;
283         }
284
285         com_core_packet_send_only(s_info.fd, packet);
286         packet_destroy(packet);
287         s_info.cmd = SLAVE_LIST;
288         s_info.age++;
289 }
290
291 /*!
292  * var = debug, slave_max_load
293  * cmd = set / get
294  */
295 static void send_command(const char *cmd, const char *var, const char *val)
296 {
297         struct packet *packet;
298
299         if (s_info.cmd != NOP) {
300                 printf("Previous command is not finished\n");
301                 return;
302         }
303
304         packet = packet_create_noack("master_ctrl", "sss", cmd, var, val);
305         com_core_packet_send_only(s_info.fd, packet);
306         packet_destroy(packet);
307         s_info.cmd = MASTER_CTRL;
308         s_info.age++;
309 }
310
311 static int pkglist_cb(const char *appid, const char *lbid, int is_prime, void *data)
312 {
313         struct node *parent = data;
314         struct node *node;
315         struct package *info;
316
317         node = node_find(parent, lbid);
318         if (node) {
319                 info = node_data(node);
320                 if (!info) {
321                         printf("Invalid node\n");
322                         return -EINVAL;
323                 }
324
325                 free(info->pkgid);
326                 info->pkgid = strdup(appid);
327                 if (!info->pkgid) {
328                         printf("Error: %s\n", strerror(errno));
329                         return -ENOMEM;
330                 }
331
332                 node_set_age(node, s_info.age);
333                 return 0;
334         }
335
336         info = calloc(1, sizeof(*info));
337         if (!info) {
338                 printf("Error: %s\n", strerror(errno));
339                 return -ENOMEM;
340         }
341
342         info->pkgid = strdup(appid);
343         if (!info->pkgid) {
344                 printf("Error: %s\n", strerror(errno));
345                 free(info);
346                 return -ENOMEM;
347         }
348
349         info->primary = is_prime;
350
351         node = node_create(parent, lbid, NODE_DIR);
352         if (!node) {
353                 free(info->pkgid);
354                 free(info);
355                 return -ENOMEM;
356         }
357
358         node_set_mode(node, NODE_READ | NODE_EXEC);
359         node_set_data(node, info);
360         node_set_age(node, s_info.age);
361         return 0;
362 }
363
364 static void send_pkg_list(void)
365 {
366         struct packet *packet;
367
368         if (s_info.cmd != NOP) {
369                 printf("Previous command is not finished\n");
370                 return;
371         }
372
373         packet = packet_create_noack("pkg_list", "d", 0.0f);
374         if (!packet) {
375                 printf("Failed to create a packet\n");
376                 return;
377         }
378
379         com_core_packet_send_only(s_info.fd, packet);
380         packet_destroy(packet);
381         s_info.cmd = PKG_LIST;
382         s_info.age++;
383
384         livebox_service_get_pkglist(pkglist_cb, s_info.targetdir);
385 }
386
387 static void send_inst_delete(void)
388 {
389         struct packet *packet;
390         struct node *parent;
391         const char *name;
392         struct instance *inst;
393
394         if (s_info.cmd != NOP) {
395                 printf("Previous command is not finished\n");
396                 return;
397         }
398
399         parent = node_parent(s_info.targetdir);
400         if (!parent) {
401                 printf("Invalid argument\n");
402                 return;
403         }
404
405         if (!node_parent(parent)) {
406                 printf("Invalid argument\n");
407                 return;
408         }
409
410         name = node_name(node_parent(parent));
411         if (!name || strcmp(name, "package")) {
412                 printf("Invalid argument\n");
413                 return;
414         }
415
416         inst = node_data(s_info.targetdir);
417         name = node_name(parent);
418
419         packet = packet_create_noack("pkg_ctrl", "sss", "rminst", name, inst->id);
420         com_core_packet_send_only(s_info.fd, packet);
421         packet_destroy(packet);
422         s_info.cmd = INST_CTRL;
423         s_info.age++;
424 }
425
426 static void send_inst_list(const char *pkgname)
427 {
428         struct packet *packet;
429
430         if (s_info.cmd != NOP) {
431                 printf("Previous command is not finished\n");
432                 return;
433         }
434
435         packet = packet_create_noack("inst_list", "s", pkgname);
436         if (!packet) {
437                 printf("Failed to create a packet\n");
438                 return;
439         }
440
441         com_core_packet_send_only(s_info.fd, packet);
442         packet_destroy(packet);
443         s_info.cmd = INST_LIST;
444         s_info.age++;
445 }
446
447 static inline void help(void)
448 {
449         printf("liveinfo - Livebox utility\n");
450         printf("------------------------------ [Command list] ------------------------------\n");
451         printf("\e[32mcd [PATH] - Change directory\e[0m\n");
452         printf("\e[32mls [ | PATH] - List up content as a file\e[0m\n");
453         printf("\e[32mrm [PKG_ID|INST_ID] - Delete package or instance\e[0m\n");
454         printf("\e[32mcat [FILE] - Open a file to get some detail information\e[0m\n");
455         printf("\e[32mpull [FILE] - Pull given file to host dir\e[0m\n");
456         printf("\e[32mset [debug] [on|off] Set the control variable of master provider\e[0m\n");
457         printf("\e[32mexit - \e[0m\n");
458         printf("\e[32mquit - \e[0m\n");
459         printf("----------------------------------------------------------------------------\n");
460 }
461
462 static inline void init_directory(void)
463 {
464         struct node *node;
465         s_info.rootdir = node_create(NULL, NULL, NODE_DIR);
466         if (!s_info.rootdir)
467                 return;
468         node_set_mode(s_info.rootdir, NODE_READ | NODE_EXEC);
469
470         node = node_create(s_info.rootdir, "provider", NODE_DIR);
471         if (!node) {
472                 node_destroy(s_info.rootdir);
473                 s_info.rootdir = NULL;
474                 return;
475         }
476         node_set_mode(node, NODE_READ | NODE_EXEC);
477
478         node = node_create(s_info.rootdir, "package", NODE_DIR);
479         if (!node) {
480                 node_destroy(node_child(s_info.rootdir));
481                 node_destroy(s_info.rootdir);
482                 s_info.rootdir = NULL;
483                 return;
484         }
485         node_set_mode(node, NODE_READ | NODE_EXEC);
486
487         s_info.curdir = s_info.rootdir;
488         return;
489 }
490
491 static inline void fini_directory(void)
492 {
493 }
494
495 static inline void do_command(const char *cmd)
496 {
497         char command[256];
498         char argument[4096] = { '\0', };
499
500         if (!strlen(cmd) || *cmd == '#') {
501                 prompt(NULL);
502                 return;
503         }
504
505         if (sscanf(cmd, "%255[^ ] %s", command, argument) == 2)
506                 cmd = command;
507
508         if (!strcasecmp(cmd, "exit") || !strcasecmp(cmd, "quit")) {
509                 ecore_main_loop_quit();
510         } else if (!strcasecmp(cmd, "set")) {
511                 char variable[4096] = { '0', };
512                 char value[4096] = { '0', };
513
514                 if (sscanf(argument, "%4095[^ ] %s", variable, value) != 2) {
515                         printf("Invalid argument(%s): set [VAR] [VAL]\n", argument);
516                         goto out;
517                 }
518
519                 send_command(cmd, variable, value);
520         } else if (!strcasecmp(cmd, "get")) {
521                 send_command(cmd, argument, "");
522         } else if (!strcasecmp(cmd, "ls")) {
523                 const char *name;
524                 struct node *parent;
525
526                 if (*argument) {
527                         s_info.targetdir = (*argument == '/') ? s_info.rootdir : s_info.curdir;
528                         s_info.targetdir = node_find(s_info.targetdir, argument);
529                 } else {
530                         s_info.targetdir = s_info.curdir;
531                 }
532
533                 if (!s_info.targetdir) {
534                         printf("%s is not exists\n", argument);
535                         goto out;
536                 }
537
538                 name = node_name(s_info.targetdir);
539                 if (name) {
540                         if (!strcmp(name, "package")) {
541                                 if (s_info.cmd == NOP) {
542                                         send_pkg_list();
543                                         return;
544                                 }
545
546                                 printf("Waiting the server response\n");
547                                 goto out;
548                         } else if (!strcmp(name, "provider")) {
549                                 if (s_info.cmd == NOP) {
550                                         send_slave_list();
551                                         return;
552                                 }
553
554                                 printf("Waiting the server response\n");
555                                 goto out;
556                         }
557                 }
558
559                 parent = node_parent(s_info.targetdir);
560                 if (parent && node_name(parent)) {
561                         if (!strcmp(node_name(parent), "package")) {
562                                 if (s_info.cmd != NOP) {
563                                         printf("Waiting the server response\n");
564                                         goto out;
565                                 }
566                                 send_inst_list(name);
567                                 return;
568                         }
569                 }
570
571                 ls();
572         } else if (!strcasecmp(cmd, "cd")) {
573                 if (!*argument)
574                         goto out;
575
576                 if (s_info.cmd != NOP) {
577                         printf("Waiting the server response\n");
578                         goto out;
579                 }
580
581                 s_info.targetdir = (*argument == '/') ? s_info.rootdir : s_info.curdir;
582                 s_info.targetdir = node_find(s_info.targetdir, argument);
583                 if (!s_info.targetdir) {
584                         printf("%s is not exists\n", argument);
585                         goto out;
586                 }
587
588                 if (node_type(s_info.targetdir) != NODE_DIR) {
589                         printf("Unable change directory to %s\n", argument);
590                         goto out;
591                 }
592
593                 if (!(node_mode(s_info.targetdir) & NODE_EXEC)) {
594                         printf("Access denied %s\n", argument);
595                         goto out;
596                 }
597
598                 s_info.curdir = s_info.targetdir;
599         } else if (!strcasecmp(cmd, "rm")) {
600                 if (!*argument)
601                         goto out;
602
603                 if (s_info.cmd != NOP) {
604                         printf("Waiting the server response\n");
605                         goto out;
606                 }
607
608                 s_info.targetdir = (*argument == '/') ? s_info.rootdir : s_info.curdir;
609                 s_info.targetdir = node_find(s_info.targetdir, argument);
610                 if (!s_info.targetdir) {
611                         printf("%s is not exists\n", argument);
612                         goto out;
613                 }
614
615                 if (!(node_mode(s_info.targetdir) & NODE_WRITE)) {
616                         printf("Access denied %s\n", argument);
617                         goto out;
618                 }
619
620                 send_inst_delete();
621         } else if (!strcasecmp(cmd, "help")) {
622                 help();
623         } else {
624                 printf("Unknown command - \"help\"\n");
625         }
626
627 out:
628         prompt(NULL);
629         return;
630 }
631
632 static Eina_Bool input_cb(void *data, Ecore_Fd_Handler *fd_handler)
633 {
634         static int idx = 0;
635         static char cmd_buffer[256];
636         char ch;
637         int fd;
638         int ret;
639
640         if (fd_handler) {
641                 fd = ecore_main_fd_handler_fd_get(fd_handler);
642                 if (fd < 0) {
643                         printf("FD is not valid: %d\n", fd);
644                         return ECORE_CALLBACK_CANCEL;
645                 }
646         } else {
647                 fd = s_info.input_fd;
648         }
649
650         /*!
651          * \note
652          * Using this routine, we can implement the command recommend algorithm.
653          * When a few more characters are matched with history of command, we can show it to user
654          * Then the user will choose one or write new command
655          */
656
657         /* Silly.. Silly */
658         while ((ret = read(fd, &ch, sizeof(ch))) == sizeof(ch)) {
659                 switch (ch) {
660                 case 0x08: /* BKSP */
661                         cmd_buffer[idx] = '\0';
662                         if (idx > 0) {
663                                 idx--;
664                                 cmd_buffer[idx] = ' ';
665                                 putc('\r', stdout);
666                                 prompt(cmd_buffer);
667                         }
668
669                         cmd_buffer[idx] = '\0';
670                         putc('\r', stdout);
671                         prompt(cmd_buffer);
672                         break;
673                 case '\n':
674                 case '\r':
675                         cmd_buffer[idx] = '\0';
676                         idx = 0;
677                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
678                                 putc((int)'\n', stdout);
679                         do_command(cmd_buffer);
680                         memset(cmd_buffer, 0, sizeof(cmd_buffer));
681
682                         /* Make a main loop processing for command handling */
683                         return ECORE_CALLBACK_RENEW;
684                 default:
685                         cmd_buffer[idx++] = ch;
686
687                         if (s_info.input_fd == STDIN_FILENO || s_info.verbose)
688                                 putc((int)ch, stdout);
689
690                         if (idx == sizeof(cmd_buffer) - 1) {
691                                 cmd_buffer[idx] = '\0';
692                                 printf("\nCommand buffer is overflow: %s\n", cmd_buffer);
693                                 idx = 0;
694                         }
695                         break;
696                 }
697         }
698
699         if (ret < 0 && !fd_handler)
700                 ecore_main_loop_quit();
701
702         return ECORE_CALLBACK_RENEW;
703 }
704
705 static void processing_line_buffer(const char *buffer)
706 {
707         int pid;
708         char slavename[256];
709         char pkgname[256];
710         char abi[256];
711         char inst_id[4096];
712         char cluster[256];
713         char category[256];
714         char state[10];
715         int refcnt;
716         int fault_count;
717         int list_count;
718         int loaded_inst;
719         int loaded_pkg;
720         double ttl;
721         int secured;
722         double period;
723         int width;
724         int height;
725         struct node *node;
726         struct package *pkginfo;
727         struct instance *instinfo;
728         struct slave *slaveinfo;
729         int i;
730
731         switch (s_info.cmd) {
732         case PKG_LIST:
733                 if (sscanf(buffer, "%d %255[^ ] %255[^ ] %255[^ ] %d %d %d", &pid, slavename, pkgname, abi, &refcnt, &fault_count, &list_count) != 7) {
734                         printf("Invalid format : [%s]\n", buffer);
735                         return;
736                 }
737
738                 node = node_find(s_info.targetdir, pkgname);
739                 if (!node) {
740                         pkginfo = calloc(1, sizeof(*pkginfo));
741                         if (!pkginfo) {
742                                 printf("Error: %s\n", strerror(errno));
743                                 return;
744                         }
745
746                         pkginfo->pkgid = strdup("conf.file");
747                         if (!pkginfo->pkgid)
748                                 printf("Error: %s\n", strerror(errno));
749
750                         pkginfo->primary = 1;
751
752                         node = node_create(s_info.targetdir, pkgname, NODE_DIR);
753                         if (!node) {
754                                 free(pkginfo->pkgid);
755                                 free(pkginfo);
756                                 printf("Failed to create a new node (%s)\n", pkgname);
757                                 return;
758                         }
759
760                         node_set_mode(node, NODE_READ | NODE_EXEC);
761                         node_set_data(node, pkginfo);
762                 } else {
763                         pkginfo = node_data(node);
764                         if (!pkginfo) {
765                                 printf("Package info is inavlid\n");
766                                 return;
767                         }
768
769                         free(pkginfo->slavename);
770                         free(pkginfo->abi);
771
772                         pkginfo->slavename = NULL;
773                         pkginfo->abi = NULL;
774                 }
775
776                 node_set_age(node, s_info.age);
777
778                 pkginfo->slavename = strdup(slavename);
779                 if (!pkginfo->slavename)
780                         printf("Error: %s\n", strerror(errno));
781
782                 pkginfo->abi = strdup(abi);
783                 if (!pkginfo->abi)
784                         printf("Error: %s\n", strerror(errno));
785
786                 pkginfo->pid = pid;
787                 pkginfo->refcnt = refcnt;
788                 pkginfo->fault_count = fault_count;
789                 pkginfo->inst_count = list_count;
790                 break;
791         case SLAVE_LIST:
792                 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) {
793                         printf("Invalid format : [%s]\n", buffer);
794                         return;
795                 }
796                 node = node_find(s_info.targetdir, slavename);
797                 if (!node) {
798                         slaveinfo = calloc(1, sizeof(*slaveinfo));
799                         if (!slaveinfo) {
800                                 printf("Error: %s\n", strerror(errno));
801                                 return;
802                         }
803
804                         node = node_create(s_info.targetdir, slavename, NODE_DIR);
805                         if (!node) {
806                                 free(slaveinfo);
807                                 return;
808                         }
809
810                         node_set_mode(node, NODE_READ | NODE_EXEC);
811                         node_set_data(node, slaveinfo);
812                 } else {
813                         slaveinfo = node_data(node);
814                 }
815
816                 node_set_age(node, s_info.age);
817
818                 free(slaveinfo->pkgname);
819                 free(slaveinfo->abi);
820                 free(slaveinfo->state);
821
822                 slaveinfo->pkgname = strdup(pkgname);
823                 if (!slaveinfo->pkgname)
824                         printf("Error: %s\n", strerror(errno));
825
826                 slaveinfo->abi = strdup(abi);
827                 if (!slaveinfo->abi)
828                         printf("Error: %s\n", strerror(errno));
829
830                 slaveinfo->state = strdup(state);
831                 if (!slaveinfo->state)
832                         printf("Error: %s\n", strerror(errno));
833
834                 slaveinfo->pid = pid;
835                 slaveinfo->secured = secured;
836                 slaveinfo->refcnt = refcnt;
837                 slaveinfo->fault_count = fault_count;
838                 slaveinfo->loaded_inst = loaded_inst;
839                 slaveinfo->loaded_pkg = loaded_pkg;
840                 slaveinfo->ttl = ttl;
841                 break;
842         case INST_LIST:
843                 if (sscanf(buffer, "%[^ ] %[^ ] %[^ ] %lf %[^ ] %d %d", inst_id, cluster, category, &period, state, &width, &height) != 7) {
844                         printf("Invalid format : [%s]\n", buffer);
845                         return;
846                 }
847
848                 for (i = strlen(inst_id); i > 0 && inst_id[i] != '/'; i--);
849                 i += (inst_id[i] == '/');
850
851                 node = node_find(s_info.targetdir, inst_id + i);
852                 if (!node) {
853                         instinfo = calloc(1, sizeof(*instinfo));
854                         if (!instinfo) {
855                                 printf("Error: %s\n", strerror(errno));
856                                 return;
857                         }
858
859                         node = node_create(s_info.targetdir, inst_id + i, NODE_FILE);
860                         if (!node) {
861                                 free(instinfo);
862                                 return;
863                         }
864
865                         node_set_mode(node, NODE_READ | NODE_WRITE);
866                         node_set_data(node, instinfo);
867                 } else {
868                         instinfo = node_data(node);
869                 }
870
871                 node_set_age(node, s_info.age);
872
873                 free(instinfo->id);
874                 free(instinfo->cluster);
875                 free(instinfo->category);
876                 free(instinfo->state);
877
878                 instinfo->id = strdup(inst_id);
879                 if (!instinfo->id)
880                         printf("Error: %s\n", strerror(errno));
881
882                 instinfo->cluster = strdup(cluster);
883                 if (!instinfo->cluster)
884                         printf("Error: %s\n", strerror(errno));
885
886                 instinfo->category = strdup(category);
887                 if (!instinfo->category)
888                         printf("Error: %s\n", strerror(errno));
889
890                 instinfo->state = strdup(state);
891                 if (!instinfo->state)
892                         printf("Error: %s\n", strerror(errno));
893
894                 instinfo->period = period;
895                 instinfo->width = width;
896                 instinfo->height = height;
897                 break;
898         case INST_CTRL:
899                 sscanf(buffer, "%d", &i);
900                 printf("%s\n", strerror(i));
901                 printf("Result: %d\n", i);
902                 break;
903         case SLAVE_CTRL:
904                 sscanf(buffer, "%d", &i);
905                 printf("Result: %d\n", i);
906                 break;
907         case MASTER_CTRL:
908                 sscanf(buffer, "%d", &i);
909                 printf("Result: %d\n", i);
910                 break;
911         default:
912                 break;
913         }
914 }
915
916 static inline void do_line_command(void)
917 {
918         switch (s_info.cmd) {
919         case PKG_LIST:
920                 ls();
921                 break;
922         case INST_LIST:
923                 ls();
924                 break;
925         case SLAVE_LIST:
926                 ls();
927                 break;
928         case INST_CTRL:
929                 break;
930         case SLAVE_CTRL:
931                 break;
932         case MASTER_CTRL:
933                 break;
934         default:
935                 break;
936         }
937         prompt(NULL);
938 }
939
940 static Eina_Bool read_cb(void *data, Ecore_Fd_Handler *fd_handler)
941 {
942         int fd;
943         static char *line_buffer = NULL;
944         static int line_index = 0;
945         static int bufsz = 256;
946         char ch;
947
948         fd = ecore_main_fd_handler_fd_get(fd_handler);
949         if (fd < 0) {
950                 printf("FD is not valid: %d\n", fd);
951                 return ECORE_CALLBACK_CANCEL;
952         }
953
954         if (read(fd, &ch, sizeof(ch)) != sizeof(ch)) {
955                 printf("Error: %s\n", strerror(errno));
956                 return ECORE_CALLBACK_CANCEL;
957         }
958
959         if (!line_buffer) {
960                 line_index = 0;
961                 line_buffer = malloc(bufsz);
962                 if (!line_buffer) {
963                         printf("Error: %s\n", strerror(errno));
964                         return ECORE_CALLBACK_CANCEL;
965                 }
966         }       
967
968         if (ch == '\n') { /* End of a line */
969                 if (line_index == bufsz - 1) {
970                         char *new_buf;
971                         new_buf = realloc(line_buffer, bufsz + 2);
972                         if (!new_buf) {
973                                 printf("Error: %s\n", strerror(errno));
974                                 free(line_buffer);
975                                 line_buffer = NULL;
976                                 line_index = 0;
977                                 bufsz = 256;
978                                 return ECORE_CALLBACK_CANCEL;
979                         }
980
981                         line_buffer = new_buf;
982                 }
983
984                 line_buffer[line_index] = '\0';
985
986                 if (!strcmp(line_buffer, "EOD")) {
987                         do_line_command();
988                         s_info.cmd = NOP;
989                 } else {
990                         processing_line_buffer(line_buffer);
991                 }
992
993                 free(line_buffer);
994                 line_buffer = NULL;
995                 line_index = 0;
996                 bufsz = 256;
997         } else {
998                 char *new_buf;
999
1000                 line_buffer[line_index++] = ch;
1001                 if (line_index == bufsz - 1) {
1002                         bufsz += 256;
1003                         new_buf = realloc(line_buffer, bufsz);
1004                         if (!new_buf) {
1005                                 printf("Error: %s\n", strerror(errno));
1006                                 free(line_buffer);
1007                                 line_buffer = NULL;
1008                                 line_index = 0;
1009                                 bufsz = 256;
1010                                 return ECORE_CALLBACK_CANCEL;
1011                         }
1012
1013                         line_buffer = new_buf;
1014                 }
1015         }
1016
1017         return ECORE_CALLBACK_RENEW;
1018 }
1019
1020 static int ret_cb(pid_t pid, int handle, const struct packet *packet, void *data)
1021 {
1022         const char *fifo_name;
1023         int ret;
1024
1025         if (packet_get(packet, "si", &fifo_name, &ret) != 2) {
1026                 printf("Invalid packet\n");
1027                 return -EFAULT;
1028         }
1029
1030         if (ret != 0) {
1031                 printf("Returns %d\n", ret);
1032                 return ret;
1033         }
1034
1035         printf("FIFO: %s\n", fifo_name);
1036
1037         s_info.fifo_handle = open(fifo_name, O_RDONLY | O_NONBLOCK);
1038         if (s_info.fifo_handle < 0) {
1039                 printf("Error: %s\n", strerror(errno));
1040                 s_info.fifo_handle = -EINVAL;
1041                 ecore_main_loop_quit();
1042                 return -EINVAL;
1043         }
1044
1045         s_info.fd_handler = ecore_main_fd_handler_add(s_info.fifo_handle, ECORE_FD_READ, read_cb, NULL, NULL, NULL);
1046         if (!s_info.fd_handler) {
1047                 printf("Failed to add a fd handler\n");
1048                 close(s_info.fifo_handle);
1049                 s_info.fifo_handle = -EINVAL;
1050                 ecore_main_loop_quit();
1051                 return -EFAULT;
1052         }
1053
1054         prompt(NULL);
1055
1056         if (s_info.input_fd == STDIN_FILENO) {
1057                 if (fcntl(s_info.input_fd, F_SETFL, O_NONBLOCK) < 0)
1058                         printf("Error: %s\n", strerror(errno));
1059
1060                 s_info.in_handler = ecore_main_fd_handler_add(s_info.input_fd, ECORE_FD_READ, input_cb, NULL, NULL, NULL);
1061                 if (!s_info.in_handler) {
1062                         printf("Failed to add a input handler\n");
1063                         ecore_main_loop_quit();
1064                         return -EFAULT;
1065                 }
1066         }
1067
1068         return 0;
1069 }
1070
1071 static int disconnected_cb(int handle, void *data)
1072 {
1073         printf("Disconnected\n");
1074         ecore_main_loop_quit();
1075         return 0;
1076 }
1077
1078 static int connected_cb(int handle, void *data)
1079 {
1080         struct packet *packet;
1081
1082         printf("Connected\n");
1083
1084         packet = packet_create("liveinfo_hello", "d", 0.0f);
1085         if (!packet) {
1086                 printf("Failed to build a packet for hello\n");
1087                 com_core_packet_client_fini(s_info.fd);
1088                 s_info.fd = -EINVAL;
1089                 return -EFAULT;
1090         }
1091
1092         s_info.fd = handle;
1093
1094         if (com_core_packet_async_send(s_info.fd, packet, 0.0f, ret_cb, NULL) < 0) {
1095                 printf("Failed to send a packet hello\n");
1096                 packet_destroy(packet);
1097                 com_core_packet_client_fini(s_info.fd);
1098                 s_info.fd = -EINVAL;
1099                 return -EFAULT;
1100         }
1101
1102         packet_destroy(packet);
1103         return 0;
1104 }
1105
1106 int main(int argc, char *argv[])
1107 {
1108         struct termios ttystate;
1109         static struct method s_table[] = {
1110                 {
1111                         .cmd = NULL,
1112                         .handler = NULL,
1113                 },
1114         };
1115         static struct option long_options[] = {
1116                 { "batchmode", required_argument, 0, 'b' },
1117                 { "help", no_argument, 0, 'h' },
1118                 { "verbose", required_argument, 0, 'v' },
1119                 { 0, 0, 0, 0 }
1120         };
1121         int option_index;
1122         int c;
1123
1124         do {
1125                 c = getopt_long(argc, argv, "b:hv:", long_options, &option_index);
1126                 switch (c) {
1127                 case 'b':
1128                         if (!optarg || !*optarg) {
1129                                 printf("Invalid argument\n");
1130                                 help();
1131                                 return -EINVAL;
1132                         }
1133
1134                         if (s_info.input_fd != STDIN_FILENO) {
1135                                 /* Close the previously, opened file */
1136                                 close(s_info.input_fd);
1137                         }
1138
1139                         s_info.input_fd = open(optarg, O_RDONLY);
1140                         if (s_info.input_fd < 0) {
1141                                 printf("Unable to access %s (%s)\n", optarg, strerror(errno));
1142                                 return -EIO;
1143                         }
1144                         break;
1145                 case 'h':
1146                         help();
1147                         return 0;
1148                 case 'v':
1149                         if (!optarg || !*optarg) {
1150                                 printf("Invalid argument\n");
1151                                 help();
1152                                 return -EINVAL;
1153                         }
1154
1155                         s_info.verbose = !strcmp(optarg, "true");
1156                         break;
1157                 default:
1158                         break;
1159                 }
1160         } while (c != -1);
1161
1162         ecore_init();
1163         g_type_init();
1164
1165         com_core_add_event_callback(CONNECTOR_DISCONNECTED, disconnected_cb, NULL);
1166         com_core_add_event_callback(CONNECTOR_CONNECTED, connected_cb, NULL);
1167         livebox_service_init();
1168
1169         s_info.fd = com_core_packet_client_init(SOCKET_FILE, 0, s_table);
1170         if (s_info.fd < 0) {
1171                 printf("Failed to make a connection\n");
1172                 return -EIO;
1173         }
1174
1175         if (s_info.input_fd == STDIN_FILENO) {
1176                 printf("Type your command on below empty line\n");
1177
1178                 if (tcgetattr(s_info.input_fd, &ttystate) < 0) {
1179                         printf("Error: %s\n", strerror(errno));
1180                 } else {
1181                         ttystate.c_lflag &= ~(ICANON | ECHO);
1182                         ttystate.c_cc[VMIN] = 1;
1183
1184                         if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1185                                 printf("Error: %s\n", strerror(errno));
1186                 }
1187         } else {
1188                 printf("Batch mode enabled\n");
1189         }
1190
1191         if (setvbuf(stdout, (char *)NULL, _IONBF, 0) != 0)
1192                 printf("Error: %s\n", strerror(errno));
1193
1194         init_directory();
1195
1196         ecore_main_loop_begin();
1197
1198         fini_directory();
1199         livebox_service_fini();
1200
1201         if (s_info.fd > 0) {
1202                 com_core_packet_client_fini(s_info.fd);
1203                 s_info.fd = -EINVAL;
1204         }
1205
1206         if (s_info.fd_handler) {
1207                 ecore_main_fd_handler_del(s_info.fd_handler);
1208                 s_info.fd_handler = NULL;
1209         }
1210
1211         if (s_info.input_fd == STDIN_FILENO) {
1212                 ttystate.c_lflag |= ICANON | ECHO;
1213                 if (tcsetattr(s_info.input_fd, TCSANOW, &ttystate) < 0)
1214                         printf("Error: %s\n", strerror(errno));
1215         } else {
1216                 close(s_info.input_fd);
1217         }
1218
1219         if (s_info.fifo_handle > 0) {
1220                 close(s_info.fifo_handle);
1221                 s_info.fifo_handle = -EINVAL;
1222         }
1223
1224         if (s_info.in_handler) {
1225                 ecore_main_fd_handler_del(s_info.in_handler);
1226                 s_info.in_handler = NULL;
1227         }
1228
1229         ecore_shutdown();
1230         putc((int)'\n', stdout);
1231         return 0;
1232 }
1233
1234 /* End of a file */