Source code formating unification
[platform/framework/web/wrt.git] / src / wrt-launcher / wrt-launcher.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 #include <iostream>
17 #include <string>
18 #include <app.h>
19 #include <app_manager.h>
20 #include <string.h>
21 #include <getopt.h>
22 #include <stdlib.h>
23 #include <signal.h>
24 #include <unistd.h>
25 #include <pwd.h>
26 #include <sys/types.h>
27 #include <dpl/wrt-dao-ro/WrtDatabase.h>
28 #include <dpl/wrt-dao-ro/widget_dao_read_only.h>
29 #include <dpl/wrt-dao-ro/feature_dao_read_only.h>
30 #include <dpl/wrt-dao-ro/common_dao_types.h>
31 #include <dpl/wrt-dao-ro/wrt_db_types.h>
32 #include <dpl/wrt-dao-rw/global_dao.h>
33 #include <dpl/wrt-dao-ro/global_dao_read_only.h>
34 #include <dpl/wrt-dao-ro/config_parser_data.h>
35 #include <dpl/exception.h>
36
37 #define TIMEOUT_DEFAULT     10
38 #define ROOT_DEFAULT_UID 0
39 #define ROOT_DEFAULT_GID 0
40 #define WEBAPP_DEFAULT_UID  5000
41 #define WEBAPP_DEFAULT_GID  5000
42 #define LOGGING_DEFAULT_GID 6509
43 #define RETURN_ERROR -1
44
45 static const char *program;
46
47 class DBConnection
48 {
49   public:
50     void AttachDatabase()
51     {
52         WrtDB::WrtDatabase::attachToThreadRW();
53     }
54
55     void DetachDatabase()
56     {
57         WrtDB::WrtDatabase::detachFromThread();
58     }
59 };
60
61 static std::unique_ptr<DBConnection> g_dbConnection;
62
63 typedef struct
64 {
65     char* guid;           /**< the widget's id
66                            * (read from its config.xml during installation)*/
67     char* name;         /**< the widget's name
68                          * (read from its config.xml during installation)*/
69     char* version;      /**< the widget's varsion
70                          * (read from its config.xml during installation)*/
71     char* pkg_name;     /**< the widget's pkg name */
72 } widget_info;
73
74 static void free_widget_info(widget_info* widget_info)
75 {
76     if (widget_info) {
77         delete[] widget_info->guid;
78         delete[] widget_info->name;
79         delete[] widget_info->version;
80         delete[] widget_info->pkg_name;
81         delete widget_info;
82     }
83 }
84
85 static char* new_strdup(const char *str)
86 {
87     size_t size = strlen(str);
88     char* ret = new char[size + 1];
89     strcpy(ret, str);
90     return ret;
91 }
92
93 static bool attachDbConnection()
94 {
95     if (NULL == g_dbConnection.get()) {
96         Try {
97             g_dbConnection.reset(new DBConnection());
98             g_dbConnection->AttachDatabase();
99         }
100         Catch(DPL::DB::SqlConnection::Exception::Base) {
101             LogDebug("Fail to connect DB");
102             return FALSE;
103         }
104     }
105     return TRUE;
106 }
107
108 static bool display_widget_info()
109 {
110     if (!attachDbConnection()) {
111         return FALSE;
112     }
113
114     WidgetDAOReadOnlyList widgetList =
115         WrtDB::WidgetDAOReadOnly::getWidgetList();
116
117     printf("%3s %32s %16s %64s %16s\n",
118            "No", "Name", "Version", "GUID", "Package Name");
119     printf("%3s %32s %16s %64s %16s\n",
120            "--", "--", "----", "-------", "----");
121
122     int number = 1;
123     FOREACH(dao, widgetList) {
124         widget_info *info = new widget_info;
125         memset(info, 0x00, sizeof(widget_info));
126
127         WrtDB::WidgetGUID guid = (*dao)->getGUID();
128         DPL::Optional<DPL::String> version = (*dao)->getVersion();
129         WrtDB::WidgetPkgName package_name = (*dao)->getPkgName();
130
131         /*get WidgetName*/
132         DPL::Optional<DPL::String> widget_name;
133         DPL::OptionalString dl = (*dao)->getDefaultlocale();
134         WrtDB::WidgetLocalizedInfo localizedInfo;
135         if (dl.IsNull()) {
136             DPL::String languageTag(L"");
137             localizedInfo = (*dao)->getLocalizedInfo(languageTag);
138         } else {
139             localizedInfo = (*dao)->getLocalizedInfo(*dl);
140         }
141
142         widget_name = localizedInfo.name;
143
144         /*end get WidgetName*/
145         if (!widget_name.IsNull()) {
146             info->name = new_strdup(DPL::ToUTF8String(*widget_name).c_str());
147         }
148         if (!version.IsNull()) {
149             info->version = new_strdup(DPL::ToUTF8String(*version).c_str());
150         } else {
151             std::string installedWidgetVersionString;
152             installedWidgetVersionString = "";
153             info->version = new_strdup(installedWidgetVersionString.c_str());
154         }
155         if (!guid.IsNull()) {
156             info->guid = new_strdup(DPL::ToUTF8String(*guid).c_str());
157         }
158
159         info->pkg_name = new_strdup(DPL::ToUTF8String(package_name).c_str());
160
161         printf("%3i %32s %16s %64s %16s\n",
162                number++,
163                !info->name ? "[NULL]" : info->name,
164                !info->version ? "[NULL]" : info->version,
165                !info->guid ? "[NULL]" : info->guid,
166                !info->pkg_name ? "[NULL]" : info->pkg_name);
167
168         free_widget_info(info);
169     }
170
171     return 1;
172 }
173
174 static void print_help(FILE *stream, int /*exit_code*/)
175 {
176     fprintf(stream, "Usage : %s [ ... ]\n", program);
177     fprintf(
178         stream,
179         "   -h                       --help              Display this usage information.\n"
180         "   -l                       --list              Display installed widgets list\n"
181         "   -s [GUID]or[PkgName]     --start             Launch widget with package name or GUID\n"
182         "   -k [GUID]or[PkgName]     --kill              Kill widget with package name or GUID\n"
183         "   -r [GUID]or[PkgName]     --is-running        Check whether widget is running by package name or GUID,\n"
184         "                                                If widget is running, 0(zero) will be returned.\n"
185         "   -d                       --debug             Activate debug mode\n"
186         "   -t [second]              --timeout           Set timeout of response from widget in debug mode\n"
187         "   -v [1]or[0]              --developer-mode    Set developermode\n"
188         "   -c [1]or[0]              --compliance-mode   Set compliancemode\n"
189         "   -i [imei]                --fake-imei         Set fakeimei\n"
190         "   -m [meid]                --fake-meid         Set fakemeid\n"
191         "    if you emit this option, 5 seconds is set in debug mode\n"
192         );
193 }
194
195 static void sighandler(int signo, siginfo_t *si, void *data);
196
197 int main(int argc, char* argv[])
198 {
199     UNHANDLED_EXCEPTION_HANDLER_BEGIN
200     {
201         int next_opt, opt_idx = 0;
202         int timeout = TIMEOUT_DEFAULT;
203         char pkgname[256] = "";
204         char temp_arg[256] = "";
205         char pid[6] = "";
206         char op = '\0';
207         bool isDebugMode = false;
208         struct sigaction sigact;
209         bool dispHelp = false;
210         bool dispList = false;
211
212         service_h serviceHandle = NULL;
213         int ret = SERVICE_ERROR_NONE;
214
215         program = argv[0];
216
217         static struct option long_options[] = {
218             { "help", no_argument, 0, 'h' },
219             { "list", no_argument, 0, 'l' },
220             { "start", required_argument, 0, 's' },
221             { "kill", required_argument, 0, 'k' },
222             { "is-running", required_argument, 0, 'r' },
223             { "debug", no_argument, 0, 'd' },
224             { "timeout", required_argument, 0, 't' },
225             { "developer-mode", required_argument, 0, 'v' },
226             { "compliance-mode", required_argument, 0, 'c' },
227             { "fake-imei", required_argument, 0, 'i' },
228             { "fake-meid", required_argument, 0, 'm' },
229             { 0, 0, 0, 0 }
230         };
231
232         if (argv[1] == NULL) {
233             /* exit if any argument doesn't exist */
234             print_help(stdout, 0);
235             return -1;
236         }
237
238         if (ROOT_DEFAULT_UID == geteuid()) {
239             if (RETURN_ERROR == setuid(ROOT_DEFAULT_UID)) {
240                 perror("Fail to set uid");
241             }
242         }
243         if (ROOT_DEFAULT_GID == getegid()) {
244             if (RETURN_ERROR == setgid(ROOT_DEFAULT_GID)) {
245                 perror("Fail to set gid");
246             }
247         }
248
249         do {
250             next_opt = getopt_long(argc,
251                                    argv,
252                                    "hls:k:r:dt:v:c:i:m:",
253                                    long_options,
254                                    &opt_idx);
255
256             switch (next_opt) {
257             case 'h':
258                 if (!dispHelp) {
259                     print_help(stdout, 0);
260                     dispHelp = true;
261                 }
262                 break;
263
264             case 'l':
265                 if (dispList) {
266                     break;
267                 }
268                 if (!display_widget_info()) {
269                     printf("Fail to display the list of installed widgets");
270                     return -1;
271                 }
272                 dispList = true;
273                 break;
274
275             case 's':
276             case 'k':
277             case 'r':
278                 strncpy(temp_arg, optarg, strlen(optarg));
279                 op = next_opt;
280                 break;
281
282             case 't':
283                 timeout = atoi(optarg);
284                 if (timeout < 0) {
285                     timeout = TIMEOUT_DEFAULT;
286                 }
287                 break;
288
289             case 'd':
290                 // create service
291                 ret = service_create(&serviceHandle);
292                 if (SERVICE_ERROR_NONE != ret && NULL == serviceHandle) {
293                     LogError("Fail to create service");
294                     return FALSE;
295                 }
296
297                 // set debug mode
298                 ret = service_add_extra_data(serviceHandle,
299                                              "debug",
300                                              "true");
301                 if (SERVICE_ERROR_NONE != ret) {
302                     LogError("Fail to set debug mode [" << ret << "]");
303                     service_destroy(serviceHandle);
304                     return FALSE;
305                 }
306
307                 // set pid
308                 snprintf(pid, sizeof(pid), "%d", getpid());
309                 ret = service_add_extra_data(serviceHandle,
310                                              "pid",
311                                              pid);
312                 if (SERVICE_ERROR_NONE != ret) {
313                     LogError("Fail to set pid [" << ret << "]");
314                     service_destroy(serviceHandle);
315                     return FALSE;
316                 }
317                 isDebugMode = true;
318                 break;
319
320             case 'v':
321                 strncpy(temp_arg, optarg, strlen(optarg));
322                 if (!attachDbConnection()) {
323                     return FALSE;
324                 }
325                 if (!strcmp("1", temp_arg)) {
326                     WrtDB::GlobalDAO::SetDeveloperMode(true);
327                 } else {
328                     WrtDB::GlobalDAO::SetDeveloperMode(false);
329                 }
330                 break;
331             case 'c':
332                 strncpy(temp_arg, optarg, strlen(optarg));
333                 if (!attachDbConnection()) {
334                     return FALSE;
335                 }
336                 if (!strcmp("1", temp_arg)) {
337                     WrtDB::GlobalDAO::setComplianceMode(true);
338                 } else {
339                     WrtDB::GlobalDAO::setComplianceMode(false);
340                 }
341                 break;
342             case 'i':
343                 strncpy(temp_arg, optarg, strlen(optarg));
344                 if (!attachDbConnection()) {
345                     return FALSE;
346                 }
347                 WrtDB::GlobalDAO::setComplianceFakeImei(temp_arg);
348                 break;
349             case 'm':
350                 strncpy(temp_arg, optarg, strlen(optarg));
351                 if (!attachDbConnection()) {
352                     return FALSE;
353                 }
354                 WrtDB::GlobalDAO::setComplianceFakeMeid(temp_arg);
355                 break;
356
357             case -1:
358                 break;
359
360             default:
361                 print_help(stdout, 0);
362                 break;
363             }
364         } while (next_opt != -1);
365
366         if ((op == 's') || (op == 'k') || (op == 'r')) {
367             std::string temp;
368
369             if (NULL == g_dbConnection.get()) {
370                 Try {
371                     g_dbConnection.reset(new DBConnection());
372                     g_dbConnection->AttachDatabase();
373                 }
374                 Catch(DPL::DB::SqlConnection::Exception::Base) {
375                     LogDebug("Fail to connect DB");
376                     return FALSE;
377                 }
378             }
379             DPL::OptionalString normal_str = DPL::FromUTF8String(temp_arg);
380             WrtDB::NormalizeAndTrimSpaceString(normal_str);
381             std::string normal_arg = DPL::ToUTF8String(*normal_str);
382
383             WidgetDAOReadOnlyList widgetList =
384                 WrtDB::WidgetDAOReadOnly::getWidgetList();
385             FOREACH(dao, widgetList) {
386                 WrtDB::WidgetGUID d_guid = (*dao)->getGUID();
387                 WrtDB::WidgetPkgName d_pkgname = (*dao)->getPkgName();
388                 if (!d_guid.IsNull() &&
389                     !strcmp(DPL::ToUTF8String(*d_guid).c_str(), temp_arg))
390                 {
391                     WrtDB::WidgetPkgName package_name = (*dao)->getPkgName();
392                     temp = DPL::ToUTF8String(package_name);
393                     break;
394                 }
395                 if (!strcmp(DPL::ToUTF8String(d_pkgname).c_str(),
396                             normal_arg.c_str()))
397                 {
398                     WrtDB::WidgetPkgName package_name = (*dao)->getPkgName();
399                     temp = DPL::ToUTF8String(package_name);
400                     break;
401                 }
402             }
403
404             if (!temp.empty()) {
405                 strncpy(pkgname, temp.c_str(), strlen(temp.c_str()));
406             } else {
407                 printf("result: %s\n", "failed");
408                 return -1;
409             }
410         }
411
412         if (op == 's') {
413             /* check if this is request for debug mode, or not */
414             if (true == isDebugMode) {
415                 /* wait for return from the widget */
416                 sigemptyset(&sigact.sa_mask);
417                 sigact.sa_flags = SA_SIGINFO;
418                 sigact.sa_restorer = NULL;
419                 sigact.sa_sigaction = sighandler;
420
421                 if (sigaction(SIGRTMIN, &sigact, 0) == 1) {
422                     printf("result: %s\n", "failed");
423                     return -1;
424                 }
425             } else {
426                 // case of "-d" option, service_create is already allocated
427                 // create service
428                 ret = service_create(&serviceHandle);
429                 if (SERVICE_ERROR_NONE != ret && NULL == serviceHandle) {
430                     printf("result: %s\n", "failed");
431                     return -1;
432                 }
433             }
434
435             if (strlen(pkgname) > 0) {
436                 // do setuid to '5000' uid to communicate
437                 //with webapp using RT signal.
438                 gid_t group_list[1];
439                 group_list[0] = LOGGING_DEFAULT_GID;
440
441                 if (setgroups(sizeof(group_list), group_list) < 0) {
442                     printf("result: %s\n", "failed");
443                     return -1;
444                 }
445
446                 if (setreuid(WEBAPP_DEFAULT_UID, WEBAPP_DEFAULT_GID) < 0) {
447                     printf("result: %s\n", "failed");
448                     return -1;
449                 }
450
451                 // set package
452                 ret = service_set_package(serviceHandle, pkgname);
453                 if (SERVICE_ERROR_NONE != ret) {
454                     printf("result: %s\n", "failed");
455                     service_destroy(serviceHandle);
456                     return -1;
457                 }
458
459                 //launch service
460                 ret = service_send_launch_request(serviceHandle, NULL, NULL);
461                 if (SERVICE_ERROR_NONE != ret) {
462                     printf("result: %s\n", "failed");
463                     service_destroy(serviceHandle);
464                     return -1;
465                 }
466
467                 service_destroy(serviceHandle);
468             } else {
469                 printf("result: %s\n", "failed");
470                 return -1;
471             }
472
473             if (true == isDebugMode) {
474                 // wait RTS signal from widget by 5 second
475                 sleep(timeout);
476                 printf("result: %s\n", "failed");
477                 return -1;
478             }
479             // This text should be showed for IDE
480             printf("result: %s\n", "launched");
481             return 0;
482         } else if (op == 'k') {
483             bool isRunning = false;
484
485             //checks whether the application is running
486             ret = app_manager_is_running(pkgname, &isRunning);
487             if (APP_MANAGER_ERROR_NONE != ret) {
488                 printf("result: %s\n", "failed");
489                 return -1;
490             }
491
492             if (true == isRunning) {
493                 // get app_context for running application
494                 // app_context must be released with app_context_destroy
495                 app_context_h appCtx = NULL;
496                 ret = app_manager_get_app_context(pkgname, &appCtx);
497                 if (APP_MANAGER_ERROR_NONE != ret) {
498                     printf("result: %s\n", "failed");
499                     return -1;
500                 }
501
502                 // terminate app_context_h
503                 ret = app_manager_terminate_app(appCtx);
504                 if (APP_MANAGER_ERROR_NONE != ret) {
505                     printf("result: %s\n", "failed");
506                     app_context_destroy(appCtx);
507                     return -1;
508                 } else {
509                     printf("result: %s\n", "killed");
510                     app_context_destroy(appCtx);
511                     return 0;
512                 }
513             } else {
514                 printf("result: %s\n", "App isn't running");
515                 return 0;
516             }
517         } else if (op == 'r') {
518             bool isRunning = false;
519
520             ret = app_manager_is_running(pkgname, &isRunning);
521
522             if (APP_MANAGER_ERROR_NONE != ret) {
523                 printf("result: %s\n", "failed");
524                 return -1;
525             }
526
527             if (true == isRunning) {
528                 printf("result: %s\n", "running");
529                 return 0;
530             } else {
531                 printf("result: %s\n", "not running");
532                 return -1;
533             }
534         }
535
536         return 0;
537     }
538     UNHANDLED_EXCEPTION_HANDLER_END
539 }
540
541 static void sighandler(int signo, siginfo_t *si, void* /*data*/)
542 {
543     /* check if this signal is type of RTS */
544     if (si->si_code == SI_QUEUE) {
545         //int port;
546         //printf("RTS pid : %d\n", si->si_pid);
547         //port = (int) si->si_value.sival_ptr;
548         //printf("RTS debug port : %d\n", port);
549         // This sival_int is wrt's status (like WRT_SUCCESS..)
550         // enum WRT_SUCCESS is 0
551         if (si->si_value.sival_int > 0) {
552             printf("port: %d\n", (int)si->si_value.sival_int);
553             printf("result: %s\n", "launched");
554         } else {
555             printf("result: %s\n", "failed");
556         }
557     } else {
558         printf("Not RT signal : %d\n", signo);
559     }
560     exit(0);
561 }
562