4 author: José Bollo <jose.bollo@iot.bzh>
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
30 #include <sys/types.h>
32 extern char **environ;
35 #include "afm-launch.h"
36 #include "secmgr-wrap.h"
39 %I icondir FWK_ICON_DIR
41 %S secret params->secret
42 %D datadir params->datadir
45 %t tag (smack label) desc->tag
47 %c content desc->content
48 %m mime-type desc->type
50 %p plugins desc->plugins
52 %H height desc->height
55 static const char *launch_master_args[] = {
64 static const char *launch_html_args[] = {
71 "http://localhost:%P",
76 static const char *launch_bin_args[] = {
82 static const char *launch_qml_args[] = {
90 const char **launch_args;
93 { "text/html", launch_html_args },
94 { "application/x-executable", launch_bin_args },
95 { "application/octet-stream", launch_bin_args },
96 { "text/vnd.qt.qml", launch_qml_args }
105 static char **instantiate_arguments(const char **args, struct afm_launch_desc *desc, struct launchparam *params)
107 const char **iter, *p, *v;
108 char *data, **result, port[20], width[20], height[20], mini[3], c;
115 /* loop that either compute the size and build the result */
125 while((c = *p++) != 0) {
134 case 'I': v = FWK_ICON_DIR; break;
135 case 'P': if(!x) sprintf(port, "%d", params->port); v = port; break;
136 case 'S': v = params->secret; break;
137 case 'D': v = params->datadir; break;
138 case 'r': v = desc->path; break;
139 case 'h': v = desc->home; break;
140 case 't': v = desc->tag; break;
141 case 'a': v = desc->appid; break;
142 case 'c': v = desc->content; break;
143 case 'm': v = desc->type; break;
144 case 'n': v = desc->name; break;
145 case 'p': v = "" /*desc->plugins*/; break;
146 case 'W': if(!x) sprintf(width, "%d", desc->width); v = width; break;
147 case 'H': if(!x) sprintf(height, "%d", desc->height); v = height; break;
149 default: mini[1] = c; v = mini; break;
152 data = stpcpy(data, v);
167 result = malloc((n+1)*sizeof(char*) + s);
168 if (result == NULL) {
172 data = (char*)(&result[n + 1]);
177 static void mksecret(char buffer[9])
179 snprintf(buffer, 9, "%08lX", (0xffffffff & random()));
184 static int port_ring = 12345;
185 int port = port_ring;
186 if (port < 12345 || port > 15432)
188 port_ring = port + 1;
192 int afm_launch(struct afm_launch_desc *desc, pid_t children[2])
194 char datadir[PATH_MAX];
201 struct launchparam params;
204 /* what launcher ? */
206 if (desc->type != NULL && *desc->type) {
207 nkl = sizeof known_launchers / sizeof * known_launchers;
208 while (ikl < nkl && strcmp(desc->type, known_launchers[ikl].type))
211 ERROR("type %s not found!", desc->type);
218 rc = snprintf(datadir, sizeof datadir, "%s/%s", desc->home, desc->tag);
219 if (rc < 0 || rc >= sizeof datadir) {
220 ERROR("overflow for datadir");
225 /* make the secret and port */
230 params.secret = secret;
231 params.datadir = datadir;
233 /* prepare the pipes */
234 rc = pipe2(mpipe, O_CLOEXEC);
236 ERROR("error while calling pipe2: %m");
239 rc = pipe2(spipe, O_CLOEXEC);
241 ERROR("error while calling pipe2: %m");
247 /* fork the master child */
248 children[0] = fork();
249 if (children[0] < 0) {
250 ERROR("master fork failed: %m");
258 /********* in the parent process ************/
261 /* wait the ready signal (that transmit the slave pid) */
262 rc = read(mpipe[0], &children[1], sizeof children[1]);
264 ERROR("reading master pipe failed: %m");
270 assert(rc == sizeof children[1]);
271 /* start the child */
272 rc = write(spipe[1], "start", 5);
274 ERROR("writing slave pipe failed: %m");
283 /********* in the master child ************/
287 /* enter the process group */
290 ERROR("setpgid failed");
294 /* enter security mode */
295 rc = secmgr_prepare_exec(desc->tag);
297 ERROR("call to secmgr_prepare_exec failed: %m");
301 /* enter the datadirectory */
302 rc = mkdir(datadir, 0755);
303 if (rc && errno != EEXIST) {
304 ERROR("creation of datadir %s failed: %m", datadir);
309 ERROR("can't enter the datadir %s: %m", datadir);
313 /* fork the slave child */
314 children[1] = fork();
315 if (children[1] < 0) {
316 ERROR("slave fork failed: %m");
319 if (children[1] == 0) {
320 /********* in the slave child ************/
322 rc = read(spipe[0], message, sizeof message);
324 ERROR("reading slave pipe failed: %m");
328 args = instantiate_arguments(known_launchers[ikl].launch_args, desc, ¶ms);
330 ERROR("out of memory in slave");
333 rc = execve(args[0], args, environ);
334 ERROR("failed to exec slave %s: %m", args[0]);
339 /********* still in the master child ************/
341 args = instantiate_arguments(launch_master_args, desc, ¶ms);
343 ERROR("out of memory in master");
346 rc = write(mpipe[1], &children[1], sizeof children[1]);
348 ERROR("can't write master pipe: %m");
352 rc = execve(args[0], args, environ);
353 ERROR("failed to exec master %s: %m", args[0]);