nuttx-apps/system/nxinit/parser.c

309 lines
6.6 KiB
C
Raw Permalink Normal View History

system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
/****************************************************************************
* apps/system/nxinit/parser.c
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "init.h"
#include "parser.h"
/****************************************************************************
* Public Functions
****************************************************************************/
int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv)
{
bool quote = false;
bool new = true;
int i = 0;
for (; ; )
system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
{
while (isblank(*buf))
{
if (!quote)
{
*buf = '\0';
new = true;
}
buf++;
}
if (*buf == '-' && *(buf + 1) == '-')
{
argv[i++] = buf;
if (i >= argc || *(buf += 2) == '\0')
{
break;
}
while (isblank(*buf))
{
*buf++ = '\0';
}
argv[i++] = buf;
break;
}
if (*buf == '\"')
{
*buf = '\0';
if (quote)
{
quote = false;
buf++;
system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
}
else
{
quote = true;
new = true;
buf++;
}
}
if (*buf == '\0')
{
break;
}
system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
if (new)
{
argv[i++] = buf;
if (i >= argc)
{
break;
}
new = false;
}
buf++;
}
if (dup && i > 0)
{
argc = i;
for (i = 0; i < argc; i++)
{
argv[i] = strdup(argv[i]);
if (!argv[i])
{
while (i-- > 0)
{
free(argv[i]);
}
return -errno;
}
}
}
return i;
}
int init_parse_config_file(FAR const struct parser_s *parser,
FAR const char *file)
{
char buf[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX];
FAR const struct parser_s *cur = NULL;
bool create = false;
FAR char *nl;
size_t n = 0;
int ret = 0;
int fd;
#ifdef CONFIG_SYSTEM_NXINIT_DEBUG
int line = 0;
#endif
init_debug("Parsing %s", file);
fd = open(file, O_RDONLY | O_CLOEXEC);
if (fd < 0)
{
init_err("Opening %s %d", file, errno);
return -errno;
}
for (; ; )
{
ssize_t r = read(fd, &buf[n], sizeof(buf) - n);
if (r < 0)
{
if (errno == EINTR)
{
continue;
}
ret = -errno;
goto out;
}
else if (r == 0)
{
if (n == 0)
{
break;
}
buf[n++] = '\n';
}
n += r;
while ((nl = memchr(buf, '\n', n)))
{
*(nl++) = '\0';
n -= nl - buf;
init_debug("Line %3d: '%s'", ++line, buf);
if (*buf == '\0')
{
continue;
}
system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
/* Skip empty lines and lines containing only whitespace */
for (ret = 0; buf[ret] && isblank(buf[ret]); ret++);
if (buf[ret] == '\0')
{
memmove(buf, nl, n);
continue;
}
system/nxinit: Add NuttX Init This component (abbreviated as "NxInit") is specifically developed for NuttX and intended for system initialization. While we have adopted the Android Init Language among various syntax options, this is a brand-new implementation—it is not a port or variant of Android Init. Refer to the implementation of Android Init Language, consists of five broad classes of statements: Actions, Commands, Services, Options, and Imports. Actions support two types of triggers: event and action. Action triggers also support runtime triggering. Services support lifecycle management, including automatic restart (at specified intervals), and starting/stopping individually or by class. Import supports files or directories, and we may add a static method in the future. The following are some differences: 1. The Android Init Language treats lines starting with `#` as comments, while we use a preprocessor to handle comments. 2. For action commands, we can omit "exec" and directly execute built-in apps or nsh builtins. 3. Regarding the property service, users can either adapt it by self or directly use the preset NVS-based properties. 4. Only part of standard action commands and service options are implemented currlently. To enable system/nxinit: ```diff -CONFIG_INIT_ENTRYPOINT="nsh_main" +CONFIG_INIT_ENTRYPOINT="init_main" +CONFIG_SYSTEM_NXINIT=y ``` For format and additional details, refer to: https://android.googlesource.com/platform/system/core/+/ master/init/README.md Signed-off-by: wangjianyu3 <wangjianyu3@xiaomi.com>
2025-08-14 21:45:53 +08:00
for (ret = 0; parser[ret].key; ret++)
{
if (!strncmp(parser[ret].key, buf, strlen(parser[ret].key)))
{
create = true;
cur = &parser[ret];
init_debug("New section (%s)", parser[ret].key);
break;
}
}
if (cur == NULL)
{
ret = -EINVAL;
goto out;
}
ret = cur->parse(cur, create, buf);
create = false;
if (ret < 0)
{
goto out;
}
memmove(buf, nl, n);
}
if (n == sizeof(buf))
{
ret = -E2BIG;
goto out;
}
}
for (n = 0; parser[n].key; n++)
{
if (parser[n].check)
{
ret = parser[n].check(&parser[n]);
if (ret < 0)
{
break;
}
}
}
out:
close(fd);
if (ret < 0)
{
init_err("Parse %s %d", file, ret);
}
return ret;
}
int init_parse_configs(FAR const struct parser_s *parser,
FAR const char *path)
{
FAR struct dirent *entry;
char file[PATH_MAX];
struct stat sb;
FAR DIR *dir;
int ret = 0;
size_t i;
if (stat(path, &sb) < 0)
{
init_err("Stat %s", path);
return -errno;
}
if (S_ISDIR(sb.st_mode))
{
dir = opendir(path);
if (dir == NULL)
{
init_err("Opening directory %s", path);
return -errno;
}
while ((entry = readdir(dir)) != NULL)
{
if (DIRENT_ISFILE(entry->d_type))
{
i = strlen(entry->d_name);
if (i >= 3 && !strcmp(entry->d_name + i - 3, ".rc"))
{
snprintf(file, sizeof(file), "%s/%s", path, entry->d_name);
ret = init_parse_config_file(parser, file);
if (ret < 0)
{
break;
}
}
}
}
closedir(dir);
}
else if (S_ISREG(sb.st_mode))
{
ret = init_parse_config_file(parser, path);
}
return ret;
}