#ident "$Id: readconfig.c,v 1.7 2005/01/21 01:35:33 hpa Exp $" /* ----------------------------------------------------------------------- * * * Copyright 2004 H. Peter Anvin - All Rights Reserved * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, Inc., 53 Temple Place Ste 330, * Boston MA 02111-1307, USA; either version 2 of the License, or * (at your option) any later version; incorporated herein by reference. * * ----------------------------------------------------------------------- */ #define _GNU_SOURCE /* Needed for asprintf() on Linux */ #include #include #include #include #include #ifdef __COM32__ # include #endif #include "menu.h" int nentries = 0; int defentry = 0; int allowedit = 1; /* Allow edits of the command line */ int timeout = 0; char *menu_title = ""; char *ontimeout = NULL; char *menu_master_passwd = NULL; struct menu_entry menu_entries[MAX_ENTRIES]; struct menu_entry *menu_hotkeys[256]; #define astrdup(x) ({ char *__x = (x); \ size_t __n = strlen(__x) + 1; \ char *__p = alloca(__n); \ if ( __p ) memcpy(__p, __x, __n); \ __p; }) const char *ipappends[32]; static void get_ipappend(void) { #ifdef __COM32__ static com32sys_t r; uint16_t *ipp; int i; int nipappends; r.eax.w[0] = 0x000F; __intcall(0x22, &r, &r); nipappends = min(r.ecx.w[0], 32); ipp = MK_PTR(r.es, r.ebx.w[0]); for ( i = 0 ; i < nipappends ; i++ ) { ipappends[i] = MK_PTR(r.es, *ipp++); } #else ipappends[0] = "ip=foo:bar:baz:quux"; ipappends[1] = "BOOTIF=01-aa-bb-cc-dd-ee-ff"; #endif } static const char * get_config(void) { #ifdef __COM32__ static com32sys_t r; r.eax.w[0] = 0x000E; __intcall(0x22, &r, &r); return MK_PTR(r.es, r.ebx.w[0]); #else return "syslinux.cfg"; /* Dummy default name */ #endif } #define MAX_LINE 512 static char * skipspace(char *p) { while ( *p && *p <= ' ' ) p++; return p; } /* Check to see if we are at a certain keyword (case insensitive) */ static int looking_at(const char *line, const char *kwd) { const char *p = line; const char *q = kwd; while ( *p && *q && ((*p^*q) & ~0x20) == 0 ) { p++; q++; } if ( *q ) return 0; /* Didn't see the keyword */ return *p <= ' '; /* Must be EOL or whitespace */ } struct labeldata { char *label; char *kernel; char *append; char *menulabel; char *passwd; unsigned int ipappend; unsigned int menuhide; unsigned int menudefault; }; static void record(struct labeldata *ld, char *append) { char ipoptions[256], *ipp; int i; struct menu_entry *me = &menu_entries[nentries]; if ( ld->label ) { char *a, *s; me->displayname = ld->menulabel ? ld->menulabel : ld->label; me->label = ld->label; me->passwd = ld->passwd; me->hotkey = 0; if ( ld->menulabel ) { unsigned char *p = (unsigned char *)strchr(ld->menulabel, '^'); if ( p && p[1] ) { int hotkey = p[1] & ~0x20; if ( !menu_hotkeys[hotkey] ) { me->hotkey = hotkey; } } } ipp = ipoptions; *ipp = '\0'; for ( i = 0 ; i < 32 ; i++ ) { if ( (ld->ipappend & (1U << i)) && ipappends[i] ) ipp += sprintf(ipp, " %s", ipappends[i]); } a = ld->append; if ( !a ) a = append; if ( !a || (a[0] == '-' && !a[1]) ) a = ""; s = a[0] ? " " : ""; asprintf(&me->cmdline, "%s%s%s%s", ld->kernel, ipoptions, s, a); ld->label = NULL; free(ld->kernel); if ( ld->append ) free(ld->append); if ( !ld->menuhide ) { if ( me->hotkey ) menu_hotkeys[me->hotkey] = me; if ( ld->menudefault ) defentry = nentries; nentries++; } } } void parse_config(const char *filename) { char line[MAX_LINE], *p; FILE *f; char *append = NULL; static struct labeldata ld; get_ipappend(); if ( !filename ) filename = get_config(); f = fopen(filename, "r"); if ( !f ) return; while ( fgets(line, sizeof line, f) ) { p = strchr(line, '\r'); if ( p ) *p = '\0'; p = strchr(line, '\n'); if ( p ) *p = '\0'; p = skipspace(line); if ( looking_at(p, "menu") ) { p = skipspace(p+4); if ( looking_at(p, "title") ) { menu_title = strdup(skipspace(p+5)); } else if ( looking_at(p, "label") ) { if ( ld.label ) ld.menulabel = strdup(skipspace(p+5)); } else if ( looking_at(p, "default") ) { ld.menudefault = 1; } else if ( looking_at(p, "hide") ) { ld.menuhide = 1; } else if ( looking_at(p, "passwd") ) { ld.passwd = strdup(skipspace(p+6)); } else if ( looking_at(p, "master") ) { p = skipspace(p+6); if ( looking_at (p, "passwd") ) { menu_master_passwd = strdup(skipspace(p+6)); } } else { /* Unknown, ignore for now */ } } else if ( looking_at(p, "append") ) { char *a = strdup(skipspace(p+6)); if ( ld.label ) ld.append = a; else append = a; } else if ( looking_at(p, "label") ) { p = skipspace(p+5); record(&ld, append); ld.label = strdup(p); ld.kernel = strdup(p); ld.append = NULL; ld.menulabel = NULL; ld.ipappend = ld.menudefault = ld.menuhide = 0; } else if ( looking_at(p, "kernel") ) { if ( ld.label ) { free(ld.kernel); ld.kernel = strdup(skipspace(p+6)); } } else if ( looking_at(p, "timeout") ) { timeout = atoi(skipspace(p+7)); } else if ( looking_at(p, "ontimeout") ) { ontimeout = strdup(skipspace(p+9)); } else if ( looking_at(p, "allowoptions") ) { allowedit = atoi(skipspace(p+12)); } else if ( looking_at(p, "ipappend") ) { ld.ipappend = atoi(skipspace(p+8)); } } record(&ld, append); fclose(f); }