static int scan_keyword_assignment(struct misc_file_buffer* file, struct scan_token* token, int line) { int rc; rc = scan_keyword(file, &token->content.keyword.keyword, line); if (rc) return rc; skip_blanks(file); if (misc_get_char(file, 0) != '=') { error_reason("Line %d: unexpected characters after keyword", line); return -1; } file->pos++; skip_blanks(file); rc = scan_value_string(file, &token->content.keyword.value, line); if (rc) return rc; if (skip_trailing_blanks(file)) { error_reason("Line %d: unexpected characters at end of line", line); return -1; } token->id = scan_id_keyword_assignment; token->line = line; return 0; }
static int scan_number(struct misc_file_buffer* file, int* number, int line) { int start_pos; int old_number; int new_number; old_number = 0; new_number = 0; start_pos = file->pos; for (; isdigit(misc_get_char(file, 0)); file->pos++) { new_number = old_number*10 + misc_get_char(file, 0) - '0'; if (new_number < old_number) { error_reason("Line %d: number too large", line); return -1; } old_number = new_number; } if (file->pos == start_pos) { error_reason("Line %d: number expected", line); return -1; } *number = new_number; return 0; }
static int check_menu_keyword_data(char* keyword[], int* line, char* name, int section_line) { int i; for (i = 0; i < SCAN_KEYWORD_NUM; i++) { switch (scan_menu_key_table[i]) { case inv: if (!keyword[i]) break; error_reason("Line %d: keyword '%s' not allowed in " "menu section '%s'", line[i], scan_keyword_name( (enum scan_keyword_id) i), name); return -1; break; case req: if (keyword[i]) break; error_reason("Line %d: missing keyword '%s' " "in menu section '%s'", section_line, scan_keyword_name( (enum scan_keyword_id) i), name); return -1; default: break; } } return 0; }
static int scan_get_defaultboot_type(char* keyword[], int line[], int section_line, enum scan_section_type* type) { int key1; int key2; if (keyword[(int) scan_keyword_defaultauto]) { if (keyword[(int) scan_keyword_defaultmenu]) { key1 = (int) scan_keyword_defaultauto; key2 = (int) scan_keyword_defaultmenu; goto err_too_much; } if (!keyword[(int) scan_keyword_target]) { goto err_no_target; } *type = section_default_auto; } else if (keyword[(int) scan_keyword_target]) { if (keyword[(int) scan_keyword_defaultmenu]) { key1 = (int) scan_keyword_target; key2 = (int) scan_keyword_defaultmenu; goto err_too_much_target; } *type = section_default_auto; } else if (keyword[(int) scan_keyword_defaultmenu]) { if (keyword[(int) scan_keyword_default]) { key1 = (int) scan_keyword_defaultmenu; key2 = (int) scan_keyword_default; goto err_too_much; } *type = section_default_menu; } else if (keyword[(int) scan_keyword_default]) { *type = section_default_section; } else { error_reason("Line %d: Section '%s' requires one of keywords " "'default', 'defaultmenu', 'defaultauto' or " "'target'", section_line, DEFAULTBOOT_SECTION); return -1; } return 0; err_no_target: error_reason("Line %d: Keyword 'target' required in section '%s' when " "specifying 'defaultauto'", section_line, DEFAULTBOOT_SECTION); return -1; err_too_much: error_reason("Line %d: Only one of keywords 'default', 'defaultmenu' " "and 'defaultauto' allowed in section '%s'", MAX(line[key1], line[key2]), DEFAULTBOOT_SECTION); return -1; err_too_much_target: error_reason("Line %d: Only one of keywords 'default', 'defaultmenu' " "and 'target' allowed in section '%s'", MAX(line[key1], line[key2]), DEFAULTBOOT_SECTION); return -1; }
/* Check scanned tokens for compliance with config file rules. Return zero * if config file complies, non-zero otherwise. Rules are: * * Global: * 1 - no keywords are allowed outside of a section * * Configuration sections: * 2 - may not contain number assignments * 3 - must contain certain keywords according to type (see keyword_table) * 4 - may not contain certain keywords according to type (see keyword_table) * 5 - keywords may be specified at most once * 6 - must contain at least one keyword assignment * 7 - section name must be unique in the configuration file * 8 - defaultboot:default must point to a valid section * * Menu sections: * 9 - must contain at least one number assignment * 10 - numbers in number assignment have to be unique in the section * 11 - referenced sections must be present * 12 - must contain certain keywords according to type (see keyword_table) * 13 - may not contain certain keywords according to type (see keyword_table) * 14 - keywords may be specified at most once * 15 - menu name must be unique in the configuration file * 16 - optional default position must be a valid position * */ int scan_check(struct scan_token* scan) { int i; int rc; i = 0; while (scan[i].id != scan_id_empty) { switch (scan[i].id) { case scan_id_section_heading: rc = check_section(scan, &i); if (rc) return rc; break; case scan_id_menu_heading: rc = check_menu(scan, &i); if (rc) return rc; break; default: /* Rule 1 */ error_reason("Line %d: %s not allowed outside of " "section", scan[i].line, scan_id_name(scan[i].id)); return -1; } } return 0; }
static int scan_section_heading(struct misc_file_buffer* file, struct scan_token* token, int line) { int start_pos; int end_pos; int current; char* name; for (start_pos=file->pos; misc_get_char(file, 0) != ']'; file->pos++) { current = misc_get_char(file, 0); switch (current) { case EOF: case '\n': error_reason("Line %d: unterminated section heading", line); return -1; default: if (!(isalnum(current) || ispunct(current))) { error_reason("Line %d: invalid character in " "section name", line); return -1; } } } end_pos = file->pos; if (end_pos == start_pos) { error_reason("Line %d: empty section name", line); return -1; } file->pos++; if (skip_trailing_blanks(file)) { error_reason("Line %d: unexpected characters after section " "name", line); return -1; } name = (char *) misc_malloc(end_pos - start_pos + 1); if (name == NULL) return -1; memcpy(name, &file->buffer[start_pos], end_pos - start_pos); name[end_pos - start_pos] = 0; token->id = scan_id_section_heading; token->line = line; token->content.section.name = name; return 0; }
static int scan_menu_heading(struct misc_file_buffer* file, struct scan_token* token, int line) { int start_pos; int end_pos; int current; char* name; for (start_pos=file->pos; ; file->pos++) { current = misc_get_char(file, 0); if ((current == EOF) || (current == '\n')) break; else if (isblank(current)) break; else if (!isalnum(current)) { error_reason("Line %d: invalid character in menu name ", line); return -1; } } end_pos = file->pos; if (skip_trailing_blanks(file)) { error_reason("Line %d: blanks not allowed in menu name", line); return -1; } if (end_pos == start_pos) { error_reason("Line %d: empty menu name", line); return -1; } name = (char *) misc_malloc(end_pos - start_pos + 1); if (name == NULL) return -1; memcpy(name, &file->buffer[start_pos], end_pos - start_pos); name[end_pos - start_pos] = 0; token->id = scan_id_menu_heading; token->line = line; token->content.menu.name = name; return 0; }
static int scan_keyword(struct misc_file_buffer* file, enum scan_keyword_id* id, int line) { unsigned int i; for (i=0; i < ARRAY_SIZE(keyword_list); i++) if (match_keyword(file, keyword_list[i].keyword) == 0) { file->pos += strlen(keyword_list[i].keyword); *id = keyword_list[i].id; return 0; } error_reason("Line %d: unknown keyword", line); return -1; }
static int scan_value_string(struct misc_file_buffer* file, char** value, int line) { int quote; int start_pos; int end_pos; int last_nonspace; int current; char* string; current = misc_get_char(file, 0); if (current == '\"') { quote = '\"'; file->pos++; } else if (current == '\'') { quote = '\''; file->pos++; } else quote = 0; last_nonspace = -1; for (start_pos=file->pos;; file->pos++) { current = misc_get_char(file, 0); if ((current == EOF) || (current == '\n')) { break; } else if (quote) { if (current == quote) break; } else if (!isblank(current)) last_nonspace = file->pos; } end_pos = file->pos; if (quote) { if (current != quote) { error_reason("Line %d: unterminated quotes", line); return -1; } } else if (last_nonspace >= 0) end_pos = last_nonspace + 1; string = (char *) misc_malloc(end_pos - start_pos + 1); if (string == NULL) return -1; if (end_pos > start_pos) memcpy(string, &file->buffer[start_pos], end_pos - start_pos); string[end_pos - start_pos] = 0; *value = string; if (quote) file->pos++; return 0; }
static int scan_keyword_only_statement(struct misc_file_buffer* file, struct scan_token* token, int line) { int rc; rc = scan_keyword_only(file, &token->content.keyword.keyword, line); if (rc) return rc; if (skip_trailing_blanks(file)) { error_reason("Line %d: unexpected characters at end of line", line); return -1; } token->id = scan_id_keyword_only; token->line = line; return 0; }
static int disk_determine_dasd_type(struct disk_info *data, struct dasd_information dasd_info) { if (strncmp(dasd_info.type, "FBA ",4) == 0) data->type = disk_type_fba; else if (strncmp(dasd_info.type, "DIAG",4) == 0) data->type = disk_type_diag; else if (strncmp(dasd_info.type, "ECKD",4) == 0) { if (dasd_info.FBA_layout) data->type = disk_type_eckd_ldl; else data->type = disk_type_eckd_cdl; } else { error_reason("Unknown DASD type"); return -1; } return 0; }
/* Check section at INDEX for compliance with config file rules. Upon success, * return zero and advance INDEX to point to the end of the section. Return * non-zero otherwise. */ static int check_section(struct scan_token* scan, int* index) { char* name; char* keyword[SCAN_KEYWORD_NUM]; int keyword_line[SCAN_KEYWORD_NUM]; enum scan_section_type type; int line; int rc; name = scan[*index].content.section.name; /* Ensure unique section names */ line = scan_find_section(scan, name, scan_id_section_heading, *index+1); if (line >= 0) { error_reason("Line %d: section name '%s' already specified", scan[line].line, name); return -1; } line = scan[*index].line; /* Get keyword data and advance index to end of section */ rc = scan_get_section_keywords(scan, index, name, keyword, keyword_line, NULL, NULL); if (rc) return rc; /* Check already done in scan_check_defaultboot */ if (strcmp(name, DEFAULTBOOT_SECTION) == 0) return 0; else type = section_invalid; /* Check section data */ rc = scan_check_section_data(keyword, keyword_line, name, line, &type); if (rc) return rc; /* Check target data */ rc = scan_check_target_data(keyword, keyword_line); if (rc) return rc; return 0; }
void EmacsPythonCommand::runPythonStringInsideTryExcept( const EmacsString &_command ) { EmacsString command( _command ); //_dbg_msg( FormatString( "runPythonStringInsideTryExcept: Command: %s" ) << command ); int pos=0; for(;;) { pos = command.index( '\n', pos ); if( pos < 0 ) break; command.insert( pos+1, '\t' ); pos = pos + 2; } EmacsString wrapped_command( FormatString( python_try_command_except_structure ) << command ); PyRun_SimpleString( wrapped_command.sdataHack() ); try { Py::Module module( "__main__" ); Py::Dict dict( module.getDict() ); Py::Object error_reason( dict[ "__bemacs_error" ] ); if( error_reason.isString() ) { std::string reason_1 = Py::String( error_reason ); commandFailed( EmacsString( EmacsString::copy, reason_1.c_str() ) ); } } catch( Py::Exception &e ) { //_dbg_msg( "runPythonStringInsideTryExcept: catch()" ); e.clear(); } }
/* * Copy data from scan array to keyword/number assignment array. Return 0 * on success, non-zero otherwise. * * If keyword X is specified in the section, keyword[X] contains the value of * that keyword and keyword_line[x] the line in which the keyword was defined. * Otherwise keyword[X] contains NULL. * If number assignment X is specified in the section, num[X - 1] contains * the value of that assignment and num_line the line in which the assignment * was found. Otherwise num[X - 1] contains NULL. If num is NULL, an error * is reported if a number assignment is found. */ static int scan_get_section_keywords(struct scan_token* scan, int* index, char* name, char* keyword[], int keyword_line[], char** num, int* num_line) { int i; int id; int key; int line; int number; char* value; /* Initialize array data. */ for (i = 0; i < SCAN_KEYWORD_NUM; i++) { keyword[i] = NULL; keyword_line[i] = 0; } if (num) { for (i = 0; i < BOOT_MENU_ENTRIES; i++) { num[i] = NULL; num_line[i] = 0; } } /* Extract data for keyword and number assignments. */ for (i = *index + 1; !scan_is_delimiter(scan[i].id); i++) { id = (int) scan[i].id; line = scan[i].line; /* Handle number assignments first. */ if (id == scan_id_number_assignment) { number = scan[i].content.number.number; /* Check if number assignments are expected. */ if (!num) { error_reason("Line %d: number assignment not " "allowed in section '%s'", line, name); return -1; } /* Check for valid numbers. */ if (number <= 0) { error_reason("Line %d: position must be " "greater than zero", line); return -1; } if (number > BOOT_MENU_ENTRIES) { error_reason("Line %d: position must not " "exceed %d", line, BOOT_MENU_ENTRIES); return -1; } /* Rule 10 */ if (num[number - 1]) { error_reason("Line %d: position %d already " "specified", line, number); return -1; } num[number - 1] = scan[i].content.number.value; num_line[number - 1] = line; continue; } /* Handle keyword assignments. */ if (id == scan_id_keyword_assignment) { key = scan[i].content.keyword.keyword; value = scan[i].content.keyword.value; } else if (id == scan_id_keyword_only) { key = scan[i].content.keyword_only.keyword; /* Define a dummy value. */ value = ""; } else { continue; } if (keyword[key]) { /* Rule 5 */ error_reason("Line %d: keyword '%s' already specified", line, scan_keyword_name(key)); return -1; } keyword[key] = value; keyword_line[key] = line; } *index = i; return 0; }
/* Check menu section at INDEX for compliance with config file rules. Upon * success, return zero and advance INDEX to point to the end of the section. * Return non-zero otherwise. */ static int check_menu(struct scan_token* scan, int* index) { char* keyword[SCAN_KEYWORD_NUM]; int keyword_line[SCAN_KEYWORD_NUM]; char* num[BOOT_MENU_ENTRIES]; int num_line[BOOT_MENU_ENTRIES]; char* menu_name; int menu_line; char dummy; int i; int rc; int number; int num_configs; menu_name = scan[*index].content.menu.name; menu_line = scan[*index].line; /* Rule 15 */ i = scan_find_section(scan, menu_name, scan_id_menu_heading, *index + 1); if (i >= 0) { error_reason("Line %d: menu name '%s' already specified", scan[i].line, menu_name); return -1; } /* Get keyword and number assignment data */ rc = scan_get_section_keywords(scan, index, menu_name, keyword, keyword_line, num, num_line); if (rc) return rc; /* Check for required and invalid keywords */ rc = check_menu_keyword_data(keyword, keyword_line, menu_name, menu_line); if (rc) return rc; /* Check default value */ i = (int) scan_keyword_default; if (keyword[i]) { if (sscanf(keyword[i], "%d %c", &number, &dummy) != 1) { error_reason("Line %d: default position must be a " "number", keyword_line[i]); return -1; } if (number < 1) { error_reason("Line %d: default position must be " "greater than zero", keyword_line[i]); return -1; } if (number > BOOT_MENU_ENTRIES) { error_reason("Line %d: default position too large", keyword_line[i]); return -1; } if (!num[number - 1]) { error_reason("Line %d: menu position %d not defined", keyword_line[i], number); return -1; } } /* Check prompt value */ i = (int) scan_keyword_prompt; if (keyword[i]) { if (sscanf(keyword[i], "%d %c", &number, &dummy) != 1) { error_reason("Line %d: prompt value must be a number", keyword_line[i]); return -1; } if (number != 0 && number != 1) { error_reason("Line %d: prompt value is out of range " "(must be 0 or 1)", keyword_line[i]); return -1; } } /* Check timeout value */ i = (int) scan_keyword_timeout; if (keyword[i]) { if (sscanf(keyword[i], "%d %c", &number, &dummy) != 1) { error_reason("Line %d: timeout value must be a number", keyword_line[i]); return -1; } if (number < 0) { error_reason("Line %d: timeout value is out of range", keyword_line[i]); return -1; } } /* Check number assignments */ num_configs = 0; for (i = 0; i < BOOT_MENU_ENTRIES; i++) { if (!num[i]) continue; if (scan_find_section(scan, num[i], scan_id_section_heading, 0) < 0) { error_reason("Line %d: section '%s' not found", num_line[i], num[i]); return -1; } num_configs++; } /* Check for boot configurations */ if (num_configs == 0) { error_reason("Line %d: no boot configuration specified in " "menu '%s'", menu_line, menu_name); return -1; } /* Check target data */ rc = scan_check_target_data(keyword, keyword_line); if (rc) return rc; return 0; }
int scan_check_target_data(char* keyword[], int* line) { int cylinders, heads, sectors; char dummy; int number; enum scan_keyword_id errid; if (keyword[(int) scan_keyword_targetbase] == 0) { if (keyword[(int) scan_keyword_targettype] != 0) errid = scan_keyword_targettype; else if ((keyword[(int) scan_keyword_targetgeometry] != 0)) errid = scan_keyword_targetgeometry; else if ((keyword[(int) scan_keyword_targetblocksize] != 0)) errid = scan_keyword_targetblocksize; else if ((keyword[(int) scan_keyword_targetoffset] != 0)) errid = scan_keyword_targetoffset; else return 0; if (line != NULL) error_reason("Line %d: keyword 'targetbase' required " "when specifying '%s'", line[(int) errid], scan_keyword_name(errid)); else error_reason("Option 'targetbase' required when " "specifying '%s'", scan_keyword_name(errid)); return -1; } if (keyword[(int) scan_keyword_targettype] == 0) { if (line != NULL) error_reason("Line %d: keyword 'targettype' " "required when specifying 'targetbase'", line[(int) scan_keyword_targetbase]); else error_reason("Option 'targettype' required " "when specifying 'targetbase'"); return -1; } switch (scan_get_target_type(keyword[(int) scan_keyword_targettype])) { case target_type_cdl: case target_type_ldl: if ((keyword[(int) scan_keyword_targetgeometry] != 0)) break; if (line != NULL) error_reason("Line %d: keyword 'targetgeometry' " "required when specifying 'targettype' %s", line[(int) scan_keyword_targettype], keyword[(int) scan_keyword_targettype]); else error_reason("Option 'targetgeometry' required when " "specifying 'targettype' %s", keyword[(int) scan_keyword_targettype]); return -1; case target_type_scsi: case target_type_fba: if ((keyword[(int) scan_keyword_targetgeometry] == 0)) break; if (line != NULL) error_reason("Line %d: keyword " "'targetgeometry' not allowed for " "'targettype' %s", line[(int) scan_keyword_targetgeometry], keyword[(int) scan_keyword_targettype]); else error_reason("Keyword 'targetgeometry' not " "allowed for 'targettype' %s", keyword[(int) scan_keyword_targettype]); return -1; case target_type_invalid: if (line != NULL) error_reason("Line %d: Unrecognized 'targettype' value " "'%s'", line[(int) scan_keyword_targettype], keyword[(int) scan_keyword_targettype]); else error_reason("Unrecognized 'targettype' value '%s'", keyword[(int) scan_keyword_targettype]); return -1; } if (keyword[(int) scan_keyword_targetgeometry] != 0) { if ((sscanf(keyword[(int) scan_keyword_targetgeometry], "%d,%d,%d %c", &cylinders, &heads, §ors, &dummy) != 3) || (cylinders <= 0) || (heads <= 0) || (sectors <= 0)) { if (line != NULL) error_reason("Line %d: Invalid target geometry " "'%s'", line[ (int) scan_keyword_targetgeometry], keyword[ (int) scan_keyword_targetgeometry]); else error_reason("Invalid target geometry '%s'", keyword[ (int) scan_keyword_targetgeometry]); return -1; } } if (keyword[(int) scan_keyword_targetblocksize] == 0) { if (line != NULL) error_reason("Line %d: Keyword 'targetblocksize' " "required when specifying 'targetbase'", line[(int) scan_keyword_targetbase]); else error_reason("Option 'targetblocksize' required when " "specifying 'targetbase'"); return -1; } if ((sscanf(keyword[(int) scan_keyword_targetblocksize], "%d %c", &number, &dummy) != 1) || check_blocksize(number)) { if (line != NULL) error_reason("Line %d: Invalid target blocksize '%s'", line[(int) scan_keyword_targetblocksize], keyword[(int) scan_keyword_targetblocksize]); else error_reason("Invalid target blocksize '%s'", keyword[(int) scan_keyword_targetblocksize]); return -1; } if (keyword[(int) scan_keyword_targetoffset] == 0) { if (line != NULL) error_reason("Line %d: Keyword 'targetoffset' " "required when specifying 'targetbase'", line[(int) scan_keyword_targetbase]); else error_reason("Option 'targetoffset' required when " "specifying 'targetbase'"); return -1; } if (sscanf(keyword[(int) scan_keyword_targetoffset], "%d %c", &number, &dummy) != 1) { if (line != NULL) error_reason("Line %d: Invalid target offset '%s'", line[(int) scan_keyword_targetoffset], keyword[(int) scan_keyword_targetoffset]); else error_reason("Invalid target offset '%s'", keyword[(int) scan_keyword_targetoffset]); return -1; } return 0; }
/* Check section data for correctness. KEYWORD[keyword_id] defines whether * a keyword is present, LINE[keyword_id] specifies in which line a keyword * was found or NULL when specified on command line, NAME specifies the * section name or NULL when specified on command line. */ int scan_check_section_data(char* keyword[], int* line, char* name, int section_line, enum scan_section_type* type) { char* main_keyword; int i; main_keyword = ""; /* Find out what type this section is */ if (*type == section_invalid) { if (keyword[(int) scan_keyword_tape]) { *type = section_ipl_tape; main_keyword = scan_keyword_name(scan_keyword_tape); } else if (keyword[(int) scan_keyword_image]) { *type = section_ipl; main_keyword = scan_keyword_name(scan_keyword_image); } else if (keyword[(int) scan_keyword_segment]) { *type = section_segment; main_keyword = scan_keyword_name(scan_keyword_segment); } else if (keyword[(int) scan_keyword_dumpto]) { *type = section_dump; main_keyword = scan_keyword_name(scan_keyword_dumpto); } else if (keyword[(int) scan_keyword_dumptofs]) { error_reason("Option dumptofs is deprecated, " "use dumpto instead"); return -1; } else if (keyword[(int) scan_keyword_mvdump]) { *type = section_mvdump; main_keyword = scan_keyword_name(scan_keyword_mvdump); } else { error_reason("Line %d: section '%s' must contain " "either one of keywords 'image', " "'segment', 'dumpto', 'dumptofs', " "'mvdump' or 'tape'", section_line, name); return -1; } } /* Check keywords */ for (i=0; i < SCAN_KEYWORD_NUM; i++) { switch (scan_key_table[(int) *type][i]) { case req: /* Check for missing data */ if ((keyword[i] == 0) && (line != NULL)) { /* Missing keyword in config file section */ error_reason("Line %d: missing keyword '%s' " "in section '%s'", section_line, scan_keyword_name( (enum scan_keyword_id) i), name); return -1; } else if ((keyword[i] == 0) && (line == NULL)) { /* Missing keyword on command line */ error_reason("Option '%s' required when " "specifying '%s'", scan_keyword_name( (enum scan_keyword_id) i), main_keyword); return -1; } break; case inv: /* Check for invalid data */ if ((keyword[i] != 0) && (line != NULL)) { /* Invalid keyword in config file section */ error_reason("Line %d: keyword '%s' not " "allowed in section '%s'", line[i], scan_keyword_name( (enum scan_keyword_id) i), name); return -1; } else if ((keyword[i] != 0) && (line == NULL)) { /* Invalid keyword on command line */ error_reason("Only one of options '%s' and " "'%s' allowed", main_keyword, scan_keyword_name( (enum scan_keyword_id) i)); return -1; } break; case opt: break; } } /* Additional check needed for segment */ i = (int) scan_keyword_segment; if (keyword[i] != NULL) { if (!contains_address(keyword[i])) { if (line != NULL) { error_reason("Line %d: keyword 'segment' " "requires " "load address", line[i]); } else { error_reason("Option 'segment' requires " "load address"); } return -1; } } return 0; }
/* scan_check_defaultboot checks the defaultboot section of the configuration * file. It returns * 0 on successful check, NO automenu is to be built * 1 on successful check, the automenu must be built * -1 on error */ int scan_check_defaultboot(struct scan_token* scan) { int i; int j; char* keyword[SCAN_KEYWORD_NUM]; int keyword_line[SCAN_KEYWORD_NUM]; enum scan_section_type type; int defaultboot_line; int rc; /* Check if defaultboot is defined */ i = scan_find_section(scan, DEFAULTBOOT_SECTION, scan_id_section_heading, 0); if (i < 0) { error_reason("No '%s' section found and no section specified " "on command line", DEFAULTBOOT_SECTION); return -1; } /* Ensure unique section names */ j = scan_find_section(scan, DEFAULTBOOT_SECTION, scan_id_section_heading, i + 1); if (j >= 0) { error_reason("Line %d: section name '%s' already specified", scan[j].line, DEFAULTBOOT_SECTION); return -1; } defaultboot_line = scan[i].line; /* Get keyword data */ rc = scan_get_section_keywords(scan, &i, DEFAULTBOOT_SECTION, keyword, keyword_line, NULL, NULL); if (rc) return rc; /* Check default keyword value */ i = (int) scan_keyword_default; if (keyword[i] && scan_find_section(scan, keyword[i], scan_id_section_heading, 0) < 0) { error_reason("Line %d: no such section '%s'", keyword_line[i], keyword[i]); return -1; } /* Determine default boot type */ rc = scan_get_defaultboot_type(keyword, keyword_line, defaultboot_line, &type); if (rc) return rc; /* Check target keywords */ if (type == section_default_auto && scan_count_target_keywords(keyword) > 0) { rc = scan_check_target_data(keyword, keyword_line); if (rc) return rc; } /* Check remaining section data */ rc = scan_check_section_data(keyword, keyword_line, DEFAULTBOOT_SECTION, defaultboot_line, &type); if (rc) return rc; if (type == section_default_auto) return 1; else return 0; }
struct scan_token * scan_build_automenu(struct scan_token* scan) { char* entry[BOOT_MENU_ENTRIES]; int num_entries; int default_entry; char* db_keyword[SCAN_KEYWORD_NUM]; int db_line[SCAN_KEYWORD_NUM]; char* sec_keyword[SCAN_KEYWORD_NUM]; int sec_line[SCAN_KEYWORD_NUM]; int num_targets; int num_sections; size_t size; struct scan_token* new_scan; int i; int i_new; char* name; char* default_name; int pos; /* Find defaultboot */ i = scan_find_section(scan, DEFAULTBOOT_SECTION, scan_id_section_heading, 0); /* Get defaultboot data */ if (scan_get_section_keywords(scan, &i, DEFAULTBOOT_SECTION, db_keyword, db_line, NULL, NULL)) return NULL; default_name = db_keyword[(int) scan_keyword_default]; num_targets = scan_count_target_keywords(db_keyword); /* Get size of scan array and number of sections */ num_sections = 0; for (i = 0; scan[i].id != scan_id_empty; i++) { if (scan[i].id == scan_id_section_heading) num_sections++; } size = /* old scan array + delimiter */ i + 1 + /* defaultboot heading */ 1 + /* defaultmenu */ 1 + /* menu heading */ 1 + /* keyword default,prompt,timeout */ 3 + /* target keywords*/ num_targets + /* missing target definitions */ num_sections * num_targets + /* number assigment */ num_sections; size *= sizeof(struct scan_token); new_scan = misc_malloc(size); if (!new_scan) return NULL; memset(new_scan, 0, size); /* Fill new array */ i = 0; i_new = 0; num_entries = 0; default_entry = -1; memset(entry, 0, sizeof(entry)); while (scan[i].id != scan_id_empty) { switch (scan[i].id) { case scan_id_menu_heading: name = scan[i].content.menu.name; /* Abort if automenu name is already in use */ if (strcmp(name, SCAN_AUTOMENU_NAME) == 0) { error_reason("Cannot build automenu: menu name " "'%s' already used", SCAN_AUTOMENU_NAME); goto err; } /* Menu sections are copied without changes */ if (scan_copy_section(scan, new_scan, &i, &i_new)) goto err; break; case scan_id_section_heading: name = scan[i].content.section.name; /* Do not copy old defaultboot section */ if (strcmp(name, DEFAULTBOOT_SECTION) == 0) { scan_skip_section(scan, &i); break; } /* Get section data but do not advance index */ pos = i; if (scan_get_section_keywords(scan, &pos, name, sec_keyword, sec_line, NULL, NULL)) goto err; /* Copy section contents and advance index */ if (scan_copy_section(scan, new_scan, &i, &i_new)) goto err; /* Stop here for non-IPL sections. */ if (scan_get_section_type(sec_keyword) != section_ipl) break; /* Is there enough room for another section? */ if (num_entries == BOOT_MENU_ENTRIES) { error_reason("Cannot build automenu: too many " "IPL sections defined (max %d)", BOOT_MENU_ENTRIES); goto err; } /* Determine if this is the default entry */ if (default_name && strcmp(default_name, name) == 0) default_entry = num_entries; entry[num_entries++] = name; /* Add missing target parameters if necessary */ if (scan_count_target_keywords(sec_keyword) > 0) break; if (scan_append_target_keywords(new_scan, &i_new, db_keyword)) goto err; break; default: /* Rule 1 */ error_reason("Line %d: %s not allowed outside of " "section", scan[i].line, scan_id_name(scan[i].id)); goto err; } } if (num_entries == 0) { error_reason("Cannot build automenu: no IPL entries available"); goto err; } /* Append new defaultboot and automenu sections */ /* [defaultboot] */ if (scan_append_section_heading(new_scan, &i_new, DEFAULTBOOT_SECTION)) goto err; /* defaultmenu=zipl-automatic-menu */ if (scan_append_keyword_assignment(new_scan, &i_new, scan_keyword_defaultmenu, SCAN_AUTOMENU_NAME)) goto err; /* :zipl-automatic-menu */ if (scan_append_menu_heading(new_scan, &i_new, SCAN_AUTOMENU_NAME)) goto err; /* default= */ if (default_entry >= 0) { char str[20]; snprintf(str, sizeof(str), "%d", default_entry + 1); if (scan_append_keyword_assignment(new_scan, &i_new, scan_keyword_default, str)) goto err; } /* prompt= */ i = (int) scan_keyword_prompt; if (db_keyword[i]) { if (scan_append_keyword_assignment(new_scan, &i_new, scan_keyword_prompt, db_keyword[i])) goto err; } /* timeout= */ i = (int) scan_keyword_timeout; if (db_keyword[i]) { if (scan_append_keyword_assignment(new_scan, &i_new, scan_keyword_timeout, db_keyword[i])) goto err; } /* target= */ /* targetbase= */ /* targetgeometry= */ /* targetblocksize= */ /* targetoffset= */ if (scan_append_target_keywords(new_scan, &i_new, db_keyword)) goto err; /* <num>=<section name>*/ for (i = 0; i < num_entries; i++) { if (scan_append_number_assignment(new_scan, &i_new, i + 1, entry[i])) goto err; } return new_scan; err: scan_free(new_scan); return NULL; }