Merge "Integration with security-manager" into tizen
[platform/core/appfw/aul-1.git] / src / launch.c
1 /*
2  *  aul
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>, Jaeho Lee <jaeho81.lee@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <sys/time.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <dirent.h>
31 #include <glib.h>
32
33 #include "aul.h"
34 #include "aul_api.h"
35 #include "app_sock.h"
36 #include "perf.h"
37 #include "simple_util.h"
38 #include "launch.h"
39 #include "key.h"
40 #include "aul_util.h"
41
42 static int aul_initialized = 0;
43 static int aul_fd;
44
45 static int (*_aul_handler) (aul_type type, bundle *kb, void *data) = NULL;
46 static void *_aul_data;
47
48
49
50 static int __call_aul_handler(aul_type type, bundle *kb);
51 static int app_resume();
52 static int app_terminate();
53 static void __clear_internal_key(bundle *kb);
54 static inline void __set_stime(bundle *kb);
55 static int __app_start_internal(gpointer data);
56 static int __app_launch_local(bundle *b);
57 static int __send_result_to_launchpad(int fd, int res);
58
59 static data_control_provider_handler_fn __dc_handler = NULL;
60 extern  int aul_launch_fini();
61
62 int aul_is_initialized()
63 {
64         return aul_initialized;
65 }
66
67 static int __call_aul_handler(aul_type type, bundle *kb)
68 {
69         if (_aul_handler)
70                 _aul_handler(type, kb, _aul_data);
71         return 0;
72 }
73
74 int app_start(bundle *kb)
75 {
76         const char *str = NULL;
77
78         _app_start_res_prepare(kb);
79         __call_aul_handler(AUL_START, kb);
80         // Handle the DataControl callback
81         str = bundle_get_val(kb, AUL_K_DATA_CONTROL_TYPE);
82         if (str != NULL && strcmp(str, "CORE") == 0)
83         {
84                 if (__dc_handler != NULL)
85                 {
86                         __dc_handler(kb, 0, NULL); // bundle, request_id, data
87                 }
88         }
89         return 0;
90 }
91
92 static int app_resume()
93 {
94         __call_aul_handler(AUL_RESUME, NULL);
95         return 0;
96 }
97
98 static int app_terminate()
99 {
100         __call_aul_handler(AUL_TERMINATE, NULL);
101         return 0;
102 }
103
104
105
106
107 /**
108  * @brief       encode kb and send it to 'pid'
109  * @param[in]   pid             receiver's pid
110  * @param[in]   cmd             message's status (APP_START | APP_RESULT)
111  * @param[in]   kb              data
112  */
113 SLPAPI int app_agent_send_cmd(int uid, int cmd, bundle *kb)
114 {
115         int datalen;
116         bundle_raw *kb_data;
117         int res;
118
119         bundle_encode(kb, &kb_data, &datalen);
120         if ((res = __app_agent_send_raw(uid, cmd, kb_data, datalen)) < 0) {
121                 switch (res) {
122                 case -EINVAL:
123                         res = AUL_R_EINVAL;
124                         break;
125                 case -ECOMM:
126                         res = AUL_R_ECOMM;
127                         break;
128                 case -EAGAIN:
129                         res = AUL_R_ETIMEOUT;
130                         break;
131                 case -ELOCALLAUNCH_ID:
132                         res = AUL_R_LOCAL;
133                         break;
134                 case -EILLEGALACCESS:
135                         res = AUL_R_EILLACC;
136                         break;
137                 case -ETERMINATING:
138                         res = AUL_R_ETERMINATING;
139                         break;
140                 case -ENOLAUNCHPAD:
141                         res = AUL_R_ENOLAUNCHPAD;
142                         break;
143                 default:
144                         res = AUL_R_ERROR;
145                 }
146         }
147         free(kb_data);
148
149         return res;
150 }
151
152 SLPAPI int app_agent_send_cmd_with_noreply(int uid, int cmd, bundle *kb)
153 {
154         int datalen;
155         bundle_raw *kb_data;
156         int res;
157
158         bundle_encode(kb, &kb_data, &datalen);
159         if ((res = __app_send_raw_with_noreply(uid, cmd, kb_data, datalen)) < 0) {
160                 switch (res) {
161                 case -EINVAL:
162                         res = AUL_R_EINVAL;
163                         break;
164                 case -ECOMM:
165                         res = AUL_R_ECOMM;
166                         break;
167                 case -EAGAIN:
168                         res = AUL_R_ETIMEOUT;
169                         break;
170                 case -ELOCALLAUNCH_ID:
171                         res = AUL_R_LOCAL;
172                         break;
173                 case -EILLEGALACCESS:
174                         res = AUL_R_EILLACC;
175                         break;
176                 default:
177                         res = AUL_R_ERROR;
178                 }
179         }
180         free(kb_data);
181
182         return res;
183 }
184
185
186
187
188
189
190
191
192
193 /**
194  * @brief       encode kb and send it to 'pid'
195  * @param[in]   pid             receiver's pid
196  * @param[in]   cmd             message's status (APP_START | APP_RESULT)
197  * @param[in]   kb              data
198  */
199 SLPAPI int app_send_cmd(int pid, int cmd, bundle *kb)
200 {
201         int datalen;
202         bundle_raw *kb_data;
203         int res;
204
205         bundle_encode(kb, &kb_data, &datalen);
206         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) {
207                 switch (res) {
208                 case -EINVAL:
209                         res = AUL_R_EINVAL;
210                         break;
211                 case -ECOMM:
212                         res = AUL_R_ECOMM;
213                         break;
214                 case -EAGAIN:
215                         res = AUL_R_ETIMEOUT;
216                         break;
217                 case -ELOCALLAUNCH_ID:
218                         res = AUL_R_LOCAL;
219                         break;
220                 case -EILLEGALACCESS:
221                         res = AUL_R_EILLACC;
222                         break;
223                 case -ETERMINATING:
224                         res = AUL_R_ETERMINATING;
225                         break;
226                 case -ENOLAUNCHPAD:
227                         res = AUL_R_ENOLAUNCHPAD;
228                         break;
229                 default:
230                         res = AUL_R_ERROR;
231                 }
232         }
233         free(kb_data);
234
235         return res;
236 }
237
238 SLPAPI int app_send_cmd_with_noreply(int pid, int cmd, bundle *kb)
239 {
240         int datalen;
241         bundle_raw *kb_data;
242         int res;
243
244         bundle_encode(kb, &kb_data, &datalen);
245         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0) {
246                 switch (res) {
247                 case -EINVAL:
248                         res = AUL_R_EINVAL;
249                         break;
250                 case -ECOMM:
251                         res = AUL_R_ECOMM;
252                         break;
253                 case -EAGAIN:
254                         res = AUL_R_ETIMEOUT;
255                         break;
256                 case -ELOCALLAUNCH_ID:
257                         res = AUL_R_LOCAL;
258                         break;
259                 case -EILLEGALACCESS:
260                         res = AUL_R_EILLACC;
261                         break;
262                 default:
263                         res = AUL_R_ERROR;
264                 }
265         }
266         free(kb_data);
267
268         return res;
269 }
270
271 static void __clear_internal_key(bundle *kb)
272 {
273         bundle_del(kb, AUL_K_CALLER_PID);
274         bundle_del(kb, AUL_K_APPID);
275         bundle_del(kb, AUL_K_WAIT_RESULT);
276         bundle_del(kb, AUL_K_SEND_RESULT);
277         bundle_del(kb, AUL_K_ARGV0);
278 }
279
280 static inline void __set_stime(bundle *kb)
281 {
282         struct timeval tv;
283         char tmp[MAX_LOCAL_BUFSZ];
284
285         gettimeofday(&tv, NULL);
286         snprintf(tmp, MAX_LOCAL_BUFSZ, "%ld/%ld", tv.tv_sec, tv.tv_usec);
287         bundle_add(kb, AUL_K_STARTTIME, tmp);
288 }
289
290 static int __app_start_internal(gpointer data)
291 {
292         bundle *kb;
293
294         kb = (bundle *) data;
295         app_start(kb);
296         bundle_free(kb);
297
298         return 0;
299 }
300
301 static int __app_launch_local(bundle *b)
302 {
303         if (!aul_is_initialized())
304                 return AUL_R_ENOINIT;
305
306         if (b == NULL) {
307                 _E("bundle for APP_START is NULL");
308         }
309         if (g_idle_add(__app_start_internal, b) > 0)
310                 return AUL_R_OK;
311         else
312                 return AUL_R_ERROR;
313 }
314
315 static int __app_resume_local()
316 {
317         if (!aul_is_initialized())
318                 return AUL_R_ENOINIT;
319
320         app_resume();
321
322         return 0;
323 }
324
325 /**
326  * @brief       start caller with kb
327  * @return      callee's pid
328  */
329 int app_request_to_launchpad(int cmd, const char *appid, bundle *kb)
330 {
331         int must_free = 0;
332         int ret = 0;
333
334         SECURE_LOGD("launch request : %s", appid);
335         if (kb == NULL) {
336                 kb = bundle_create();
337                 must_free = 1;
338         } else
339                 __clear_internal_key(kb);
340
341         bundle_add(kb, AUL_K_APPID, appid);
342         __set_stime(kb);
343         ret = app_send_cmd(AUL_UTIL_PID, cmd, kb);
344
345         _D("launch request result : %d", ret);
346         if (ret == AUL_R_LOCAL) {
347                 _E("app_request_to_launchpad : Same Process Send Local");
348                 bundle *b;
349
350                 switch (cmd) {
351                         case APP_START:
352                         case APP_START_RES:
353                                 b = bundle_dup(kb);
354                                 ret = __app_launch_local(b);
355                                 break;
356                         case APP_OPEN:
357                         case APP_RESUME:
358                         case APP_RESUME_BY_PID:
359                                 ret = __app_resume_local();
360                                 break;
361                         default:
362                                 _E("no support packet");
363                 }
364
365         }
366
367         /* cleanup */
368         if (must_free)
369                 bundle_free(kb);
370
371         return ret;
372 }
373
374 static int __send_result_to_launchpad(int fd, int res)
375 {
376         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
377                 if (errno == EPIPE) {
378                         _E("send failed due to EPIPE.\n");
379                         close(fd);
380                         return -1;
381                 }
382                 _E("send fail to client");
383         }
384         close(fd);
385         return 0;
386 }
387
388 /**
389  * @brief       caller & callee's sock handler
390  */
391 int aul_sock_handler(int fd)
392 {
393         app_pkt_t *pkt;
394         bundle *kbundle;
395         int clifd;
396         struct ucred cr;
397
398         const char *pid_str;
399         int pid;
400         int ret;
401
402         if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
403                 _E("recv error");
404                 return -1;
405         }
406
407         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL && cr.uid != 0) {
408                 _E("security error");
409                 __send_result_to_launchpad(clifd, -1);
410                 free(pkt);
411                 return -1;
412         }
413
414         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL) {
415                 ret = __send_result_to_launchpad(clifd, 0);
416                 if (ret < 0) {
417                         free(pkt);
418                         return -1;
419                 }
420         } else {
421                 close(clifd);
422         }
423
424         switch (pkt->cmd) {
425         case APP_START: /* run in callee */
426         case APP_START_RES:
427                 kbundle = bundle_decode(pkt->data, pkt->len);
428                 if (kbundle == NULL)
429                         goto err;
430                 app_start(kbundle);
431                 bundle_free(kbundle);
432                 break;
433
434         case APP_OPEN:  /* run in callee */
435         case APP_RESUME:
436         case APP_RESUME_BY_PID:
437                 app_resume();
438                 break;
439
440         case APP_TERM_BY_PID:   /* run in callee */
441                 app_terminate();
442                 break;
443
444         case APP_TERM_REQ_BY_PID:       /* run in callee */
445                 app_subapp_terminate_request();
446                 break;
447
448         case APP_RESULT:        /* run in caller */
449         case APP_CANCEL:
450                 kbundle = bundle_decode(pkt->data, pkt->len);
451                 if (kbundle == NULL)
452                         goto err;
453
454                 pid_str = bundle_get_val(kbundle, AUL_K_CALLEE_PID);
455                 pid = atoi(pid_str);
456
457                 app_result(pkt->cmd, kbundle, pid);
458                 bundle_free(kbundle);
459                 break;
460
461         case APP_KEY_EVENT:     /* run in caller */
462                 kbundle = bundle_decode(pkt->data, pkt->len);
463                 if (kbundle == NULL)
464                         goto err;
465                 app_key_event(kbundle);
466                 bundle_free(kbundle);
467                 break;
468
469         default:
470                 _E("no support packet");
471         }
472
473         free(pkt);
474         return 0;
475
476 err:
477         free(pkt);
478         return -1;
479 }
480
481 int aul_make_bundle_from_argv(int argc, char **argv, bundle **kb)
482 {
483         int ac = 1;
484
485         char *buf = NULL;
486
487         *kb = bundle_create();
488         if (*kb == NULL)
489                 return AUL_R_ERROR;
490
491         if (argv == NULL)
492                 return AUL_R_OK;
493
494         if ((argv != NULL) && (argv[0] != NULL)) {
495                 buf = strdup(argv[0]);
496                 if (NULL == buf) {
497                         _E("Malloc failed");
498                         return AUL_R_ERROR;
499                 }
500
501                 bundle_add(*kb, AUL_K_ARGV0, buf);
502         }
503         if (buf) {              /*Prevent FIX: ID 38717 */
504                 free(buf);
505                 buf = NULL;
506         }
507
508         while (ac < argc) {
509                 if (ac + 1 == argc) {
510                         if (bundle_add(*kb, argv[ac], "") < 0) {
511                                 _E("bundle add error pos - %d", ac);
512                                 return AUL_R_ECANCELED;
513                         }
514                 } else {
515                         if (bundle_add(*kb, argv[ac], argv[ac + 1]) < 0) {
516                                 _E("bundle add error pos - %d", ac);
517                                 return AUL_R_ECANCELED;
518                         }
519                 }
520                 ac = ac + 2;
521         }
522
523         return AUL_R_OK;
524 }
525
526 int aul_register_init_callback(
527         int (*aul_handler) (aul_type type, bundle *, void *), void *data)
528 {
529         /* Save start handler function in static var */
530         _aul_handler = aul_handler;
531         _aul_data = data;
532         return 0;
533 }
534
535 int aul_initialize()
536 {
537         if (aul_initialized) {
538                 //_E("aul already initialized");
539                 return AUL_R_ECANCELED;
540         }
541
542         aul_fd = __create_server_sock(getpid());
543         if (aul_fd < 0) {
544                 _E("aul_init create sock failed");
545                 return AUL_R_ECOMM;
546         }
547         aul_initialized = 1;
548
549         return aul_fd;
550 }
551
552 SLPAPI void aul_finalize()
553 {
554
555         aul_launch_fini();
556
557         if (aul_initialized) {
558                 close(aul_fd);
559         }
560
561         return;
562 }
563
564
565 SLPAPI int aul_launch_app(const char *appid, bundle *kb)
566 {
567         int ret;
568
569         if (appid == NULL)
570                 return AUL_R_EINVAL;
571
572         ret = app_request_to_launchpad(APP_START, appid, kb);
573         return ret;
574 }
575
576 SLPAPI int aul_open_app(const char *appid)
577 {
578         int ret;
579
580         if (appid == NULL)
581                 return AUL_R_EINVAL;
582
583         ret = app_request_to_launchpad(APP_OPEN, appid, NULL);
584         return ret;
585 }
586
587 SLPAPI int aul_resume_app(const char *appid)
588 {
589         int ret;
590
591         if (appid == NULL)
592                 return AUL_R_EINVAL;
593
594         ret = app_request_to_launchpad(APP_RESUME, appid, NULL);
595         return ret;
596 }
597
598 SLPAPI int aul_resume_pid(int pid)
599 {
600         char pkgname[MAX_PID_STR_BUFSZ];
601         int ret;
602
603         if (pid <= 0)
604                 return AUL_R_EINVAL;
605
606         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
607         ret = app_request_to_launchpad(APP_RESUME_BY_PID, pkgname, NULL);
608         return ret;
609 }
610
611 SLPAPI int aul_terminate_pid(int pid)
612 {
613         char pkgname[MAX_PID_STR_BUFSZ];
614         int ret;
615
616         if (pid <= 0)
617                 return AUL_R_EINVAL;
618
619         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
620         ret = app_request_to_launchpad(APP_TERM_BY_PID, pkgname, NULL);
621         return ret;
622 }
623
624 SLPAPI int aul_kill_pid(int pid)
625 {
626         char pkgname[MAX_PID_STR_BUFSZ];
627         int ret;
628
629         if (pid <= 0)
630                 return AUL_R_EINVAL;
631
632         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
633         ret = app_request_to_launchpad(APP_KILL_BY_PID, pkgname, NULL);
634         return ret;
635 }
636
637 SLPAPI int aul_set_data_control_provider_cb(data_control_provider_handler_fn handler)
638 {
639         __dc_handler = handler;
640         return 0;
641 }
642
643 SLPAPI int aul_unset_data_control_provider_cb(void)
644 {
645         __dc_handler = NULL;
646         return 0;
647 }
648
649 /* vi: set ts=8 sts=8 sw=8: */
650