apply FSL(Flora Software License)
[framework/system/system-server.git] / ss_launch.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
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <signal.h>
22 #include <string.h>
23 #include <errno.h>
24 #include <stdarg.h>
25 #include <stdlib.h>
26
27 #include "vconf-keys.h"
28 #include "ss_log.h"
29 #include "ss_launch.h"
30
31 #define MAX_ARGS 255
32
33 #define _S(str) ((str == NULL) ? "" : str)
34
35 int ss_set_current_lang(void)
36 {
37         char *lang;
38         int ret;
39         lang = vconf_get_str(VCONFKEY_LANGSET);
40         if (lang == NULL)
41                 return -1;
42         ret = setenv("LANG", lang, 1);
43         if (ret < 0)
44                 return -1;
45         free(lang);
46         return 0;
47 }
48
49
50 static void prepare_exec(void)
51 {
52         int i;
53         int maxfd;
54         char buf[MAX_ARGS];
55         FILE *fp;
56
57         maxfd = getdtablesize();
58         for (i = 3; i < maxfd; i++)
59                 close(i);
60
61         for (i = 0; i < _NSIG; i++)
62                 signal(i, SIG_DFL);
63
64         /* RESET oomadj value */
65         sprintf(buf,"/proc/%d/oom_adj",getpid());
66         fp = fopen(buf, "w");          
67         if (fp == NULL)                       
68                 return;                               
69         fprintf(fp, "%d", 0);                  
70         fclose(fp);
71 }
72
73 static int parse_cmd(const char *cmdline, char **argv, int max_args)
74 {
75         const char *p;
76         char *buf, *bufp;
77         int nargs = 0;
78         int escape = 0, squote = 0, dquote = 0;
79
80         if (cmdline == NULL || cmdline[0] == '\0')
81                 return -1;
82
83         bufp = buf = malloc(strlen(cmdline) + 1);
84         if (bufp == NULL || buf == NULL)
85                 return -1;
86
87         p = cmdline;
88
89         while (*p) {
90                 if (escape) {
91                         *bufp++ = *p;
92                         escape = 0;
93                 } else {
94                         switch (*p) {
95                                 case '\\':
96                                         escape = 1;
97                                         break;
98                                 case '"':
99                                         if (squote)
100                                                 *bufp++ = *p;
101                                         else
102                                                 dquote = !dquote;
103                                         break;
104                                 case '\'':
105                                         if (dquote)
106                                                 *bufp++ = *p;
107                                         else
108                                                 squote = !squote;
109                                         break;
110                                 case ' ':
111                                         if (!squote && !dquote) {
112                                                 *bufp = '\0';
113                                                 if (nargs < max_args)
114                                                         argv[nargs++] = strdup(buf);
115                                                 bufp = buf;
116                                                 break;
117                                         }
118                                 default:
119                                         *bufp++ = *p;
120                                         break;
121                         }
122                 }
123                 p++;
124         }
125
126         if (bufp != buf) {
127                 *bufp = '\0';
128                 if (nargs < max_args)
129                         argv[nargs++] = strdup(buf);
130         }
131
132         argv[nargs++] = NULL;
133
134         free(buf);
135         return nargs;
136 }
137
138 int launch_app_with_nice(const char *file, char *const argv[], pid_t *pid, int _nice)
139 {
140         int ret;
141         int _pid;
142
143         if (file == NULL || access(file, X_OK) != 0) {
144                 PRT_TRACE_ERR("launch app error: Invalid input");
145                 errno = EINVAL;
146                 return -1;
147         }
148
149         if (pid && (*pid > 0 && kill(*pid, 0) != -1))
150                 return *pid;
151
152         _pid = fork();
153
154         if (_pid == -1) {
155                 PRT_TRACE_ERR("fork error: %s", strerror(errno));
156                 /* keep errno */
157                 return -1;
158         }
159
160         if (_pid > 0) {     /* parent */
161                 if (pid)
162                         *pid = _pid;
163                 return _pid;
164         }
165
166         /* child */
167         prepare_exec();
168
169         ret = nice(_nice);
170
171         if (ret == -1 && errno != 0)
172                 PRT_TRACE_ERR("nice error: %s", strerror(errno));
173
174         ret = execvp(file, argv);
175
176         /* If failed... */
177         PRT_TRACE_ERR("exec. error: %s", strerror(errno));
178         return -2;
179 }
180
181 int launch_app_cmd_with_nice(const char *cmdline, int _nice)
182 {
183         int i;
184         int nargs;
185         int ret;
186         char *argv[MAX_ARGS + 1];
187
188         nargs = parse_cmd(cmdline, argv, MAX_ARGS + 1);
189         if (nargs == -1) {
190                 PRT_TRACE_ERR("launch app error: Invalid input");
191                 errno = EINVAL;
192                 return -1;
193         }
194
195         ret = launch_app_with_nice(argv[0], argv, NULL, _nice);
196
197         for (i = 0; i < nargs; i++)
198                 free(argv[i]);
199
200         return ret;
201 }
202
203 int launch_app_cmd(const char *cmdline)
204 {
205         return launch_app_cmd_with_nice(cmdline, 0);
206 }
207
208 int ss_launch_if_noexist(const char *execpath, const char *arg, ...)
209 {
210         char *buf;
211         int pid;
212         int nice_value = 0;
213         int flag = 0;
214         int buf_size = -1;
215         va_list argptr;
216
217         if (execpath == NULL) {
218                 errno = EINVAL;
219                 return -1;
220         }
221         if (pid = sysman_get_pid(execpath) > 0)
222                 return pid;
223
224         va_start(argptr, arg);
225         flag = va_arg(argptr, int);
226
227         if (flag & SS_LAUNCH_NICE)
228                 nice_value = va_arg(argptr, int);
229
230         va_end(argptr);
231
232         ss_set_current_lang();
233         arg = _S(arg);
234
235         buf_size = strlen(execpath) + strlen(arg) + 10;
236         buf = malloc(buf_size);
237         if (buf == NULL) {
238                 /* Do something for not enought memory error */
239                 PRT_TRACE_ERR("Malloc failed");
240                 return -1;
241         }
242
243         snprintf(buf, buf_size, "%s %s", execpath, arg);
244         pid = launch_app_cmd_with_nice(buf, nice_value);
245         if (pid == -2)
246                 exit(0);
247         free(buf);
248
249         return pid;
250 }
251
252 int ss_launch_evenif_exist(const char *execpath, const char *arg, ...)
253 {
254         char *buf;
255         int pid;
256         int nice_value = 0;
257         int flag = 0;
258         int buf_size = -1;
259
260         va_list argptr;
261
262         if (execpath == NULL) {
263                 errno = EINVAL;
264                 return -1;
265         }
266
267         va_start(argptr, arg);
268         flag = va_arg(argptr, int);
269
270         if (flag & SS_LAUNCH_NICE)
271                 nice_value = va_arg(argptr, int);
272
273         va_end(argptr);
274
275         ss_set_current_lang();
276
277         arg = _S(arg);
278
279         buf_size = strlen(execpath) + strlen(arg) + 10;
280         buf = malloc(buf_size);
281         if (buf == NULL) {
282                 /* Do something for not enought memory error */
283                 PRT_TRACE_ERR("Malloc failed");
284                 return -1;
285         }
286
287         snprintf(buf, buf_size, "%s %s", execpath, arg);
288         pid = launch_app_cmd_with_nice(buf, nice_value);
289         if (pid == -2)
290                 exit(0);
291         free(buf);
292
293         return pid;
294 }
295
296 int ss_launch_after_kill_if_exist(const char *execpath, const char *arg, ...)
297 {
298         char *buf;
299         int pid;
300         int nice_value = 0;
301         int flag = 0;
302         int buf_size = -1;
303         int exist_pid;
304         va_list argptr;
305
306         if (execpath == NULL) {
307                 errno = EINVAL;
308                 return -1;
309         }
310
311         if ((exist_pid = sysman_get_pid(execpath)) > 0)
312                 kill(exist_pid, SIGTERM);
313
314         va_start(argptr, arg);
315         flag = va_arg(argptr, int);
316
317         if (flag & SS_LAUNCH_NICE)
318                 nice_value = va_arg(argptr, int);
319
320         va_end(argptr);
321
322         ss_set_current_lang();
323
324         arg = _S(arg);
325
326         buf_size = strlen(execpath) + strlen(arg) + 10;
327         buf = malloc(buf_size);
328         if (buf == NULL) {
329                 /* Do something for not enought memory error */
330                 PRT_TRACE_ERR("Malloc Failed");
331                 return -1;
332         }
333
334         snprintf(buf, buf_size, "%s %s", execpath, arg);
335         pid = launch_app_cmd_with_nice(buf, nice_value);
336         if (pid == -2)
337                 exit(0);
338         free(buf);
339
340         return pid;
341
342 }