X-Git-Url: https://git.saurik.com/apple/system_cmds.git/blobdiff_plain/1c51fdde6f257ffe2a1b92d1a783dab947211e95..b51d5b5f06948960f0bfd4ad974e625ca2350936:/mach_init.tproj/parser.c?ds=sidebyside diff --git a/mach_init.tproj/parser.c b/mach_init.tproj/parser.c deleted file mode 100644 index e20f194..0000000 --- a/mach_init.tproj/parser.c +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights - * Reserved. This file contains Original Code and/or Modifications of - * Original Code as defined in and that are subject to the Apple Public - * Source License Version 1.0 (the 'License'). You may not use this file - * except in compliance with the License. Please obtain a copy of the - * License at http://www.apple.com/publicsource and read it before using - * this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the - * License for the specific language governing rights and limitations - * under the License." - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * bootstrap -- fundamental service initiator and port server - * Mike DeMoney, NeXT, Inc. - * Copyright, 1990. All rights reserved. - * - * parser.c -- configuration file parser - */ -#import -#import - -#import -#import -#import -#import - -#import "lists.h" -#import "bootstrap_internal.h" -#import "error_log.h" -#import "parser.h" - - -#ifndef ASSERT -#define ASSERT(p) -#endif - -#define MAX_TOKEN_LEN 128 - -#define NELEM(x) (sizeof(x)/sizeof((x)[0])) -#define LAST_ELEMENT(x) ((x)[NELEM(x)-1]) -#define STREQ(a, b) (strcmp(a, b) == 0) -#define NEW(type, num) ((type *)ckmalloc(sizeof(type) * (num))) - -typedef enum { - ASSIGN_TKN, EOF_TKN, FORWARD_TKN, INIT_TKN, NUM_TKN, - RESTARTABLE_TKN, SELF_TKN, SEMICOLON_TKN, SERVER_TKN, SERVICES_TKN, - STRING_TKN, ERROR_TKN, PRI_TKN -} token_t; - -typedef struct { - char *string; - token_t token; -} keyword_t; - -static keyword_t keywords[] = { - { "forward", FORWARD_TKN }, - { "init", INIT_TKN }, - { "priority", PRI_TKN }, - { "restartable", RESTARTABLE_TKN }, - { "self", SELF_TKN }, - { "server", SERVER_TKN }, - { "services", SERVICES_TKN }, - { NULL, ERROR_TKN } -}; - -static FILE *conf; -static int (*charget)(void); -static const char *default_conf_ptr; - -static char token_string[MAX_TOKEN_LEN]; -static token_t current_token; -static int token_num; -static int token_priority; -static int peekc; - -static int get_from_conf(void); -static int get_from_default(void); -static boolean_t parse_conf_file(void); -static boolean_t parse_self(void); -static boolean_t parse_server(void); -static boolean_t parse_service(server_t *serverp); -static boolean_t parse_pri(void); -static void advance_token(void); -static token_t keyword_lookup(void); - -/* - * init_config -- read configuration file and build-up initial server and - * service lists - * - * If can't find a suitable bootstrap.conf, use configuration given in - * bootstrap.c to get system booted so someone can correct bootstrap.conf - */ -void -init_config(void) -{ - boolean_t parse_ok; - - conf = fopen(conf_file, "r"); - if (conf != NULL) - charget = get_from_conf; - else { - error("Can't open %s -- using default configuration", conf_file); - charget = get_from_default; - } - - parse_ok = parse_conf_file(); - if ( ! parse_ok && charget == get_from_conf) { - error("Can't parse %s -- using default configuration", conf_file); - charget = get_from_default; - init_lists(); - peekc = 0; - parse_ok = parse_conf_file(); - } - if ( ! parse_ok ) - fatal("Can't parse default configuration file"); -} - -/* - * Function pointer "charget" points at get_from_conf or get_from_default - */ -static int -get_from_conf(void) -{ - return getc(conf); -} - -static int -get_from_default(void) -{ - int c; - - if (default_conf_ptr == NULL) - default_conf_ptr = default_conf; - - if (c = *default_conf_ptr) - default_conf_ptr++; - if (c == '\0') - c = EOF; - return c; -} - -/* - * What follows is a simple recursive descent parser - * ("we don't need no stinkin' yacc") - */ -static boolean_t -parse_conf_file(void) -{ - boolean_t parse_ok, good_parse; - - /* - * Configuration file syntax (and parsing routines). - * - * (parse_conf_file) - * CONF_FILE := STMT [ ; STMT ]* [ ; ] - * STMT := SERVER | SERVICE | SELF | forward | initpri - * - * (parse_server) - * SERVER := [ restartable ] ( server | init ) SERVER_PATH_ARGS [ SERVICE ] - * - * (parse_service) - * SERVICE := services [ SERVICE_DECL ]+ - * SERVICE_DECL := SERVICE_NAME - * - * (parse_self) - * SELF := self [ priority = NUM ] SERVICE_DECL - * - * Or more simply, just a list of: - * - * [[restartable] (server|init) SERVER_PATH_ARGS] [ priority = NUM ] - * [services SERVICE_NAME [ SERVICE_NAME [ = NUM ]]*] ; - * - * self [ SERVICE_NAME ]+ - * - * [ forward ] - * - */ - advance_token(); - if (current_token == EOF_TKN) { - error("Empty configuration file: %s", conf_file); - return FALSE; - } - - good_parse = TRUE; - while (current_token != EOF_TKN) { - parse_ok = TRUE; - switch (current_token) { - case RESTARTABLE_TKN: - case SERVER_TKN: - case INIT_TKN: - parse_ok = parse_server(); - break; - case SERVICES_TKN: - parse_ok = parse_service(NULL); - break; - case SELF_TKN: - parse_ok = parse_self(); - break; - case FORWARD_TKN: - forward_ok = TRUE; - advance_token(); - break; - case SEMICOLON_TKN: - advance_token(); - break; - case EOF_TKN: - break; - default: - parse_error(token_string, "start of new declaration"); - parse_ok = FALSE; - break; - } - switch (current_token) { - case SEMICOLON_TKN: - advance_token(); - break; - case EOF_TKN: - break; - default: - if (parse_ok) - parse_error(token_string, "expected ';'"); - /* Try to re-sync with input */ - while (current_token != SEMICOLON_TKN && current_token != EOF_TKN) - advance_token(); - parse_ok = FALSE; - break; - } - if (! parse_ok) - good_parse = FALSE; - } - return good_parse; -} - -static boolean_t -parse_self(void) -{ - name_t name; - - ASSERT(current_token == SELF_TKN); - advance_token(); /* Skip SELF_TKN */ - if (current_token == PRI_TKN) { - boolean_t ok; - ok = parse_pri(); - if (!ok) - return FALSE; - init_priority = token_priority; - } - while (current_token == STRING_TKN) { - if (strlen(token_string) >= sizeof(name_t)) { - parse_error(token_string, "Service name too long"); - return FALSE; - } - if (lookup_service_by_name(&bootstraps, token_string) != NULL) - { - parse_error(token_string, "Service name previously declared"); - return FALSE; - } - strcpy(name, token_string); - advance_token(); - (void) new_service(&bootstraps, name, MACH_PORT_NULL, ACTIVE, SELF, - NULL_SERVER); - } - return TRUE; -} - -static boolean_t -parse_server(void) -{ - server_t *serverp; - servertype_t servertype = SERVER; - - if (current_token == RESTARTABLE_TKN) { - advance_token(); - servertype = RESTARTABLE; - } - switch (current_token) { - case SERVER_TKN: - advance_token(); - break; - case INIT_TKN: - if (find_init_server() != NULL) { - parse_error(token_string, - "Can't specify multiple init servers"); - return FALSE; - } - if (servertype == RESTARTABLE) { - parse_error(token_string, - "Init server can not be restartable"); - return FALSE; - } - servertype = ETCINIT; - advance_token(); - break; - default: - parse_error(token_string, "expected \"server\" or \"init\""); - return FALSE; - } - if (current_token == PRI_TKN) { - boolean_t ok; - ok = parse_pri(); - if (!ok) - return FALSE; - } else - token_priority = BASEPRI_USER; - if (current_token != STRING_TKN) { - parse_error(token_string, - "expected string giving server to exec"); - return FALSE; - } - serverp = new_server(servertype, token_string, token_priority); - advance_token(); - if (current_token == SERVICES_TKN) - return parse_service(serverp); - return TRUE; -} - -static boolean_t -parse_service(server_t *serverp) -{ - name_t name; - - ASSERT(current_token == SERVICES_TKN); - advance_token(); /* Skip SERVICES_TKN */ - while (current_token == STRING_TKN) { - if (strlen(token_string) >= sizeof(name_t)) { - parse_error(token_string, "Service name too long"); - return FALSE; - } - if (lookup_service_by_name(&bootstraps, token_string) != NULL) - { - parse_error(token_string, "Service name previously declared"); - return FALSE; - } - strcpy(name, token_string); - advance_token(); - (void) new_service(&bootstraps, name, MACH_PORT_NULL, !ACTIVE, - DECLARED, serverp); - } - return TRUE; -} - -/* - * Parse priority=NUM - */ -static boolean_t -parse_pri(void) -{ - ASSERT(current_token == PRI_TKN); - advance_token(); /* Skip PRI_TKN */ - if (current_token != ASSIGN_TKN) { - parse_error(token_string, "expected '='"); - return FALSE; - } - advance_token(); /* Skip = */ - if (current_token != NUM_TKN) { - parse_error(token_string, "expected NUM"); - return FALSE; - } - advance_token(); /* Skip NUM */ - token_priority = token_num; - return TRUE; -} -/* - * advance_token -- advances input to next token - * Anything from a '#' on is comment and ignored - * - * On return: - * current_token contains token_t of next token - * token_string contains string value of next token - * if token was number, token_num contains numeric value of token - */ -static void -advance_token(void) -{ - char *cp; - -again: - while (peekc == '\0' || isspace(peekc)) - peekc = (*charget)(); - - /* Skip comments */ - if (peekc == '#') { - while (peekc != EOF && peekc != '\n') - peekc = (*charget)(); - goto again; - } - - cp = token_string; - *cp = '\0'; - - if (peekc == EOF) { - current_token = EOF_TKN; - return; - } - - if (isalpha(peekc) || peekc == '\\') { - /* - * this only allows names to be alphanumerics, '_', and - * backslash escaped characters. - * If you want something fancier, use "..." - */ - current_token = STRING_TKN; /* guarantee it's not ERROR_TKN */ - for (; isalnum(peekc) || peekc == '_' || peekc == '\\'; - peekc = (*charget)()) { - if (cp >= &LAST_ELEMENT(token_string)) { - cp = token_string; - parse_error(token_string, "token too long"); - current_token = ERROR_TKN; - } - if (peekc == '\\') - peekc = (*charget)(); - *cp++ = peekc; - } - *cp = '\0'; - if (current_token != ERROR_TKN) - current_token = keyword_lookup(); - return; - } - - /* Handle "-quoted strings */ - if (peekc == '"') { - peekc = (*charget)(); - for (; peekc != EOF && peekc != '"'; peekc = (*charget)()) { - if (cp >= &LAST_ELEMENT(token_string)) { - cp = token_string; - parse_error(token_string, "token too long"); - current_token = ERROR_TKN; - } - if (peekc == '\\') - peekc = (*charget)(); - if (peekc == '\n') { - cp = token_string; - parse_error(token_string, "Missing \""); - current_token = ERROR_TKN; - } - *cp++ = peekc; - } - if (peekc == EOF) { - cp = token_string; - parse_error(token_string, "Missing \""); - current_token = ERROR_TKN; - } else - peekc = (*charget)(); /* skip closing " */ - *cp = '\0'; - if (current_token != ERROR_TKN) - current_token = STRING_TKN; - return; - } - - if (isdigit(peekc)) { - for (token_num = 0; isdigit(peekc); peekc = (*charget)()) - token_num = token_num * 10 + peekc - '0'; - current_token = NUM_TKN; - return; - } - - if (peekc == ';') { - peekc = (*charget)(); - current_token = SEMICOLON_TKN; - return; - } - - if (peekc == '=') { - peekc = (*charget)(); - current_token = ASSIGN_TKN; - return; - } - - current_token = ERROR_TKN; - return; -} - -static token_t -keyword_lookup(void) -{ - keyword_t *kwp; - - for (kwp = keywords; kwp->string; kwp++) - if (STREQ(kwp->string, token_string)) - return kwp->token; - return STRING_TKN; -} -