1/*
2 * Copyright (C) 2009 The Android Open Source Project
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
17/* this program is used to read a set of system properties and their values
18 * from the emulator program and set them in the currently-running emulated
19 * system. It does so by connecting to the 'boot-properties' qemud service.
20 *
21 * This program should be run as root and called from
22 * /system/etc/init.goldfish.rc exclusively.
23 */
24
25#define LOG_TAG  "qemu-props"
26
27#define DEBUG  1
28
29#if DEBUG
30#  include <cutils/log.h>
31#  define  DD(...)    ALOGI(__VA_ARGS__)
32#else
33#  define  DD(...)    ((void)0)
34#endif
35
36#include <cutils/properties.h>
37#include <unistd.h>
38#include <hardware/qemud.h>
39
40/* Name of the qemud service we want to connect to.
41 */
42#define  QEMUD_SERVICE  "boot-properties"
43
44#define  MAX_TRIES      5
45
46int  main(void)
47{
48    int  qemud_fd, count = 0;
49
50    /* try to connect to the qemud service */
51    {
52        int  tries = MAX_TRIES;
53
54        while (1) {
55            qemud_fd = qemud_channel_open( "boot-properties" );
56            if (qemud_fd >= 0)
57                break;
58
59            if (--tries <= 0) {
60                DD("Could not connect after too many tries. Aborting");
61                return 1;
62            }
63
64            DD("waiting 1s to wait for qemud.");
65            sleep(1);
66        }
67    }
68
69    DD("connected to '%s' qemud service.", QEMUD_SERVICE);
70
71    /* send the 'list' command to the service */
72    if (qemud_channel_send(qemud_fd, "list", -1) < 0) {
73        DD("could not send command to '%s' service", QEMUD_SERVICE);
74        return 1;
75    }
76
77    /* read each system property as a single line from the service,
78     * until exhaustion.
79     */
80    for (;;)
81    {
82#define  BUFF_SIZE   (PROPERTY_KEY_MAX + PROPERTY_VALUE_MAX + 2)
83        DD("receiving..");
84        char* q;
85        char  temp[BUFF_SIZE];
86        int   len = qemud_channel_recv(qemud_fd, temp, sizeof temp - 1);
87
88        /* lone NUL-byte signals end of properties */
89        if (len < 0 || len > BUFF_SIZE-1 || temp[0] == '\0')
90            break;
91
92        temp[len] = '\0';  /* zero-terminate string */
93
94        DD("received: %.*s", len, temp);
95
96        /* separate propery name from value */
97        q = strchr(temp, '=');
98        if (q == NULL) {
99            DD("invalid format, ignored.");
100            continue;
101        }
102        *q++ = '\0';
103
104        if (property_set(temp, q) < 0) {
105            DD("could not set property '%s' to '%s'", temp, q);
106        } else {
107            count += 1;
108        }
109    }
110
111
112    /* finally, close the channel and exit */
113    close(qemud_fd);
114    DD("exiting (%d properties set).", count);
115    return 0;
116}
117