e82bb5ef5291bd4a0c2ae239efbfed5a20ec39ab
[framework/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 <fcntl.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <dirent.h>
30 #include <glib.h>
31
32 #include "aul.h"
33 #include "aul_api.h"
34 #include "app_sock.h"
35 #include "perf.h"
36 #include "simple_util.h"
37 #include "launch.h"
38
39 static int aul_initialized = 0;
40 static int aul_fd;
41
42 static int (*_aul_handler) (aul_type type, bundle *kb, void *data) = NULL;
43 static void *_aul_data;
44
45
46
47 static int __call_aul_handler(aul_type type, bundle *kb);
48 static int app_resume();
49 static int app_terminate();
50 static void __clear_internal_key(bundle *kb);
51 static inline void __set_stime(bundle *kb);
52 static int __app_start_internal(gpointer data);
53 static int __app_launch_local(bundle *b);
54 static int __send_result_to_launchpad(int fd, int res);
55
56
57 int aul_is_initialized()
58 {
59         return aul_initialized;
60 }
61
62 static int __call_aul_handler(aul_type type, bundle *kb)
63 {
64         if (_aul_handler)
65                 _aul_handler(type, kb, _aul_data);
66         return 0;
67 }
68
69 int app_start(bundle *kb)
70 {
71         _app_start_res_prepare(kb);
72         __call_aul_handler(AUL_START, kb);
73         return 0;
74 }
75
76 static int app_resume()
77 {
78         __call_aul_handler(AUL_RESUME, NULL);
79         return 0;
80 }
81
82 static int app_terminate()
83 {
84         __call_aul_handler(AUL_TERMINATE, NULL);
85         return 0;
86 }
87
88 /**
89  * @brief       encode kb and send it to 'pid'
90  * @param[in]   pid             receiver's pid
91  * @param[in]   cmd             message's status (APP_START | APP_RESULT)
92  * @param[in]   kb              data
93  */
94 int app_send_cmd(int pid, int cmd, bundle *kb)
95 {
96         int datalen;
97         bundle_raw *kb_data;
98         int res;
99
100         bundle_encode(kb, &kb_data, &datalen);
101         if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) {
102                 switch (res) {
103                 case -EINVAL:
104                         res = AUL_R_EINVAL;
105                         break;
106                 case -ECOMM:
107                         res = AUL_R_ECOMM;
108                         break;
109                 case -EAGAIN:
110                         res = AUL_R_ETIMEOUT;
111                         break;
112                 case -ELOCALLAUNCH_ID:
113                         res = AUL_R_LOCAL;
114                         break;
115                 default:
116                         res = AUL_R_ERROR;
117                 }
118         }
119         free(kb_data);
120
121         return res;
122 }
123
124 static void __clear_internal_key(bundle *kb)
125 {
126         bundle_del(kb, AUL_K_CALLER_PID);
127         bundle_del(kb, AUL_K_PKG_NAME);
128         bundle_del(kb, AUL_K_WAIT_RESULT);
129         bundle_del(kb, AUL_K_SEND_RESULT);
130         bundle_del(kb, AUL_K_ARGV0);
131 }
132
133 static inline void __set_stime(bundle *kb)
134 {
135         struct timeval tv;
136         char tmp[MAX_LOCAL_BUFSZ];
137
138         gettimeofday(&tv, NULL);
139         snprintf(tmp, MAX_LOCAL_BUFSZ, "%ld/%ld", tv.tv_sec, tv.tv_usec);
140         bundle_add(kb, AUL_K_STARTTIME, tmp);
141 }
142
143 static int __app_start_internal(gpointer data)
144 {
145         bundle *kb;
146
147         kb = (bundle *) data;
148         app_start(kb);
149         bundle_free(kb);
150
151         return 0;
152 }
153
154 static int __app_launch_local(bundle *b)
155 {
156         if (!aul_is_initialized())
157                 return AUL_R_ENOINIT;
158
159         if (b == NULL) {
160                 _E("bundle for APP_START is NULL");
161         }
162         if (g_idle_add(__app_start_internal, b) > 0)
163                 return AUL_R_OK;
164         else
165                 return AUL_R_ERROR;
166 }
167
168 static int __app_resume_local()
169 {
170         if (!aul_is_initialized())
171                 return AUL_R_ENOINIT;
172
173         app_resume();
174
175         return 0;
176 }
177
178 /**
179  * @brief       start caller with kb
180  * @return      callee's pid
181  */
182 int app_request_to_launchpad(int cmd, const char *pkgname, bundle *kb)
183 {
184         int must_free = 0;
185         int ret = 0;
186
187         if (kb == NULL) {
188                 kb = bundle_create();
189                 must_free = 1;
190         } else
191                 __clear_internal_key(kb);
192
193         bundle_add(kb, AUL_K_PKG_NAME, pkgname);
194         __set_stime(kb);
195         ret = app_send_cmd(LAUNCHPAD_PID, cmd, kb);
196
197         if (ret == AUL_R_LOCAL) {
198                 _E("app_request_to_launchpad : Same Process Send Local");
199                 bundle *b;
200
201                 switch (cmd) {
202                         case APP_START:
203                         case APP_START_RES:
204                                 b = bundle_dup(kb);
205                                 ret = __app_launch_local(b);
206                                 break;
207                         case APP_RESUME:
208                         case APP_RESUME_BY_PID:
209                                 ret = __app_resume_local();
210                                 break;
211                         default:
212                                 _E("no support packet");
213                 }
214
215         }
216
217         /* cleanup */
218         if (must_free)
219                 bundle_free(kb);
220
221         return ret;
222 }
223
224 static int __send_result_to_launchpad(int fd, int res)
225 {
226         if (send(fd, &res, sizeof(int), MSG_NOSIGNAL) < 0) {
227                 if (errno == EPIPE)
228                         _E("send failed due to EPIPE.\n");
229                 _E("send fail to client");
230         }
231         close(fd);
232         return 0;
233 }
234
235 /**
236  * @brief       caller & callee's sock handler  
237  */
238 int aul_sock_handler(int fd)
239 {
240         app_pkt_t *pkt;
241         bundle *kbundle;
242         int clifd;
243         struct ucred cr;
244
245         const char *pid_str;
246         int pid;
247
248         if ((pkt = __app_recv_raw(fd, &clifd, &cr)) == NULL) {
249                 _E("recv error");
250                 return -1;
251         }
252
253         if (pkt->cmd != APP_RESULT && pkt->cmd != APP_CANCEL && cr.uid != 0) {
254                 _E("security error");
255                 __send_result_to_launchpad(clifd, -1);
256                 free(pkt);
257                 return -1;
258         }
259
260         __send_result_to_launchpad(clifd, 0);
261
262         switch (pkt->cmd) {
263         case APP_START: /* run in callee */
264         case APP_START_RES:
265                 kbundle = bundle_decode(pkt->data, pkt->len);
266                 if (kbundle == NULL)
267                         goto err;
268                 app_start(kbundle);
269                 bundle_free(kbundle);
270                 break;
271
272         case APP_RESUME:        /* run in callee */
273         case APP_RESUME_BY_PID:
274                 app_resume();
275                 break;
276
277         case APP_TERM_BY_PID:   /* run in callee */
278                 app_terminate();
279                 break;
280
281         case APP_RESULT:        /* run in caller */
282         case APP_CANCEL:
283                 kbundle = bundle_decode(pkt->data, pkt->len);
284                 if (kbundle == NULL)
285                         goto err;
286
287                 pid_str = bundle_get_val(kbundle, AUL_K_CALLEE_PID);
288                 pid = atoi(pid_str);
289
290                 app_result(pkt->cmd, kbundle, pid);
291                 bundle_free(kbundle);
292                 break;
293
294         default:
295                 _E("no support packet");
296         }
297
298         free(pkt);
299         return 0;
300
301 err:
302         free(pkt);
303         return -1;
304 }
305
306 int aul_make_bundle_from_argv(int argc, char **argv, bundle **kb)
307 {
308         int ac = 1;
309
310         char *buf = NULL;
311
312         *kb = bundle_create();
313         if (*kb == NULL)
314                 return AUL_R_ERROR;
315
316         if (argv == NULL)
317                 return AUL_R_OK;
318
319         if ((argv != NULL) && (argv[0] != NULL)) {
320                 buf = strdup(argv[0]);
321                 if (NULL == buf) {
322                         _E("Malloc failed");
323                         return AUL_R_ERROR;
324                 }
325         
326                 bundle_add(*kb, AUL_K_ARGV0, buf);
327         }
328         if (buf) {              /*Prevent FIX: ID 38717 */
329                 free(buf);
330                 buf = NULL;
331         }
332
333         while (ac < argc) {
334                 if (ac + 1 == argc) {
335                         if (bundle_add(*kb, argv[ac], "") < 0) {
336                                 _E("bundle add error pos - %d", ac);
337                                 return AUL_R_ECANCELED;
338                         }
339                 } else {
340                         if (bundle_add(*kb, argv[ac], argv[ac + 1]) < 0) {
341                                 _E("bundle add error pos - %d", ac);
342                                 return AUL_R_ECANCELED;
343                         }
344                 }
345                 ac = ac + 2;
346         }
347
348         return AUL_R_OK;
349 }
350
351 int aul_register_init_callback(
352         int (*aul_handler) (aul_type type, bundle *, void *), void *data)
353 {
354         /* Save start handler function in static var */
355         _aul_handler = aul_handler;
356         _aul_data = data;
357         return 0;
358 }
359
360 int aul_initialize()
361 {
362         if (aul_initialized) {
363                 _E("aul already initialized");
364                 return AUL_R_ECANCELED;
365         }
366
367         aul_fd = __create_server_sock(getpid());
368         if (aul_fd < 0) {
369                 _E("aul_init create sock failed");
370                 return AUL_R_ECOMM;
371         }
372         aul_initialized = 1;
373
374         return aul_fd;
375 }
376
377 SLPAPI void aul_finalize()
378 {
379         int ret;
380
381         if (aul_initialized) {
382                 ret = close(aul_fd);
383         }
384
385         return;
386 }
387
388
389 SLPAPI int aul_launch_app(const char *pkgname, bundle *kb)
390 {
391         int ret;
392
393         if (pkgname == NULL)
394                 return AUL_R_EINVAL;
395
396         ret = app_request_to_launchpad(APP_START, pkgname, kb);
397         return ret;
398 }
399
400 SLPAPI int aul_open_app(const char *pkgname)
401 {
402         int ret;
403
404         if (pkgname == NULL)
405                 return AUL_R_EINVAL;
406
407         ret = app_request_to_launchpad(APP_RESUME, pkgname, NULL);
408         return ret;
409 }
410
411 SLPAPI int aul_resume_app(const char *pkgname, bundle *kb)
412 {
413         int ret;
414
415         if (pkgname == NULL)
416                 return AUL_R_EINVAL;
417
418         ret = app_request_to_launchpad(APP_RESUME, pkgname, kb);
419         return ret;
420 }
421
422 SLPAPI int aul_resume_pid(int pid)
423 {
424         char pkgname[MAX_PID_STR_BUFSZ];
425         int ret;
426
427         if (pid <= 0)
428                 return AUL_R_EINVAL;
429
430         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
431         ret = app_request_to_launchpad(APP_RESUME_BY_PID, pkgname, NULL);
432         return ret;
433 }
434
435 SLPAPI int aul_terminate_pid(int pid)
436 {
437         char pkgname[MAX_PID_STR_BUFSZ];
438         int ret;
439
440         if (pid <= 0)
441                 return AUL_R_EINVAL;
442
443         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
444         ret = app_request_to_launchpad(APP_TERM_BY_PID, pkgname, NULL);
445         return ret;
446 }
447
448 SLPAPI int aul_kill_pid(int pid)
449 {
450         char pkgname[MAX_PID_STR_BUFSZ];
451         int ret;
452
453         if (pid <= 0)
454                 return AUL_R_EINVAL;
455
456         snprintf(pkgname, MAX_PID_STR_BUFSZ, "%d", pid);
457         ret = app_request_to_launchpad(APP_KILL_BY_PID, pkgname, NULL);
458         return ret;
459 }
460
461 /* vi: set ts=8 sts=8 sw=8: */
462