1 /* -*- c -*- ------------------------------------------------------------- * 2 * 3 * Copyright 2004-2006 Murali Krishnan Ganapathy - All Rights Reserved 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation, Inc., 53 Temple Place Ste 330, 8 * Boston MA 02111-1307, USA; either version 2 of the License, or 9 * (at your option) any later version; incorporated herein by reference. 10 * 11 * ----------------------------------------------------------------------- */ 12 13 #ifndef NULL 14 #define NULL ((void *) 0) 15 #endif 16 17 #include "cmenu.h" 18 #include "help.h" 19 #include "passwords.h" 20 #include "com32io.h" 21 #include <string.h> 22 #include <stdlib.h> 23 #include <unistd.h> 24 25 #define MAX_CMD_LINE_LENGTH 514 26 27 typedef struct s_xtra { 28 long ipappend; // Stores the ipappend flag to send (useful for PXELINUX only) 29 char *argsmenu; // Stores the name of menu which contains options for the given RUN item 30 char *perms; // stores the permissions required to activate the item 31 } t_xtra; 32 33 typedef t_xtra *pt_xtra; // Pointer to extra datastructure 34 35 // Types of dot commands for which caller takes responsibility of handling 36 // In some case some commands may not make sense, it is up to the caller 37 // to handle cases which do not make sense 38 typedef enum {QUIT_CMD, REPEAT_CMD, ENTER_CMD, ESCAPE_CMD} t_dotcmd; 39 40 41 /*----------------- Global Variables */ 42 43 // default user 44 #define GUEST_USER "guest" 45 46 // for local commands. return value of execdotcmd 47 #define QUIT_CMD 0 48 #define RPT_CMD 1 49 50 char username[12]; // Name of user currently using the system 51 52 int PWD_ROW; // Line number where user authentication happens 53 int EDIT_ROW; // row where User Tab 54 55 char loginstr[] = "<L>ogin "; 56 char logoutstr[30]; 57 58 int vmode; // The video mode we want to be in 59 char timeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on timeout 60 char totaltimeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on totaltimeout 61 62 char QUITSTR[] = ".quit"; // same as exit 63 char IGNORESTR[]=".ignore"; // same as repeat, wait 64 65 /*---------------- End globals */ 66 67 // returns pointer to first non-space char 68 // and advances end of str by removing trailing spaces 69 char * strip(char *str) 70 { 71 char *p,*s,*e; 72 if (!str) return NULL; 73 p = str; 74 s = NULL; 75 e = NULL; 76 while (*p) { 77 if (*p != ' ') { 78 // mark start of string or record the last visited non-space char 79 if (!s) s=p; else e=p; 80 } 81 p++; 82 } 83 *(++e)='\0'; // kill string earlier 84 return s; 85 } 86 87 // executes a list of % separated commands 88 // non-dot commands are assumed to be syslinux commands 89 // All syslinux commands are appended with the contents of kerargs 90 // If it fails (kernel not found) then the next one is tried in the 91 // list 92 // returns QUIT_CMD or RPT_CMD 93 t_dotcmd execdotcmd(const char *cmd, char *defcmd, const char *kerargs) 94 { 95 char cmdline[MAX_CMD_LINE_LENGTH]; 96 char dotcmd[MAX_CMD_LINE_LENGTH]; 97 char *curr,*next,*p,*args; 98 char ctr; 99 100 strcpy(dotcmd,cmd); 101 next = dotcmd; 102 cmdline[0] = '\0'; 103 while (*next) { // if something to do 104 curr = next; 105 p = strchr(next,'%'); 106 if (p) { 107 *p--='\0'; next=p+2; 108 while (*p == ' ') p--; 109 *(++p)='\0'; // remove trailing spaces 110 } else { 111 if (*defcmd) { // execute defcmd next 112 next=defcmd; 113 defcmd=NULL; // exec def cmd only once 114 } else next=NULL; 115 } 116 // now we just need to execute the command "curr" 117 curr = strip(curr); 118 if (curr[0] != '.') { // just run the kernel 119 strcpy(cmdline,curr); 120 if (kerargs) strcat(cmdline,kerargs); 121 runsyslinuximage(cmdline,0); // No IPAppend 122 } else { // We have a DOT command 123 // split command into command and args (may be empty) 124 args = curr; 125 while ( (*args != ' ') && (*args != '\0') ) args++; 126 if (*args) { // found a space 127 *args++ = '\0'; 128 while (*args == ' ') args++; // skip over spaces 129 } 130 if ( (strcmp(curr,".exit")==0) || 131 (strcmp(curr,".quit")==0) 132 ) 133 return QUIT_CMD; 134 if ( (strcmp(curr,".repeat")==0) || 135 (strcmp(curr,".ignore")==0) || 136 (strcmp(curr,".wait")==0) 137 ) 138 return RPT_CMD; 139 if (strcmp(curr,".beep")==0) { 140 if ((args) && ('0' <= args[0]) && (args[0] <= '9')) 141 ctr = args[0]-'0'; 142 else ctr=1; 143 for (;ctr>0; ctr--) beep(); 144 } 145 if (strcmp(curr,".help")==0) runhelp(args); 146 } 147 } 148 return RPT_CMD; // by default we do not quit 149 } 150 151 152 TIMEOUTCODE timeout(const char *cmd) 153 { 154 t_dotcmd c; 155 c = execdotcmd(cmd,".wait",NULL); 156 switch(c) { 157 case ENTER_CMD: 158 return CODE_ENTER; 159 case ESCAPE_CMD: 160 return CODE_ESCAPE; 161 default: 162 return CODE_WAIT; 163 } 164 } 165 166 TIMEOUTCODE ontimeout(void) 167 { 168 return timeout(timeoutcmd); 169 } 170 171 TIMEOUTCODE ontotaltimeout(void) 172 { 173 return timeout(totaltimeoutcmd); 174 } 175 176 void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode) 177 { 178 int nc, nr; 179 180 if (getscreensize(1, &nr, &nc)) { 181 /* Unknown screen size? */ 182 nc = 80; 183 nr = 24; 184 } 185 186 if ( (scancode == KEY_F1) && (mi->helpid != 0xFFFF) ) { // If scancode of F1 and non-trivial helpid 187 runhelpsystem(mi->helpid); 188 } 189 190 // If user hit TAB, and item is an "executable" item 191 // and user has privileges to edit it, edit it in place. 192 if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) && 193 (EDIT_ROW < nr) && (EDIT_ROW > 0) && 194 (isallowed(username,"editcmd") || isallowed(username,"root"))) { 195 // User typed TAB and has permissions to edit command line 196 gotoxy(EDIT_ROW,1); 197 csprint("Command line:",0x07); 198 editstring(mi->data,ACTIONLEN); 199 gotoxy(EDIT_ROW,1); 200 cprint(' ',0x07,nc-1); 201 } 202 } 203 204 t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi) 205 { 206 (void)mi; // Unused 207 char pwd[40]; 208 char login[40]; 209 int nc, nr; 210 t_handler_return rv; 211 212 (void)ms; 213 214 rv = ACTION_INVALID; 215 if (PWD_ROW < 0) return rv; // No need to authenticate 216 217 if (mi->item == loginstr) { /* User wants to login */ 218 if (getscreensize(1, &nr, &nc)) { 219 /* Unknown screen size? */ 220 nc = 80; 221 nr = 24; 222 } 223 224 gotoxy(PWD_ROW,1); 225 csprint("Enter Username: ",0x07); 226 getstring(login, sizeof username); 227 gotoxy(PWD_ROW,1); 228 cprint(' ',0x07,nc); 229 csprint("Enter Password: ",0x07); 230 getpwd(pwd, sizeof pwd); 231 gotoxy(PWD_ROW,1); 232 cprint(' ',0x07,nc); 233 234 if (authenticate_user(login,pwd)) 235 { 236 strcpy(username,login); 237 strcpy(logoutstr,"<L>ogout "); 238 strcat(logoutstr,username); 239 mi->item = logoutstr; // Change item to read "Logout" 240 rv.refresh = 1; // refresh the screen (as item contents changed) 241 } 242 else strcpy(username,GUEST_USER); 243 } 244 else // User needs to logout 245 { 246 strcpy(username,GUEST_USER); 247 strcpy(logoutstr,""); 248 mi->item = loginstr; 249 } 250 251 return rv; 252 } 253 254 t_handler_return check_perms(t_menusystem *ms, t_menuitem *mi) 255 { 256 char *perms; 257 pt_xtra x; 258 259 (void) ms; // To keep compiler happy 260 261 x = (pt_xtra) mi->extra_data; 262 perms = ( x ? x->perms : NULL); 263 if (!perms) return ACTION_VALID; 264 265 if (isallowed(username,"root") || isallowed(username,perms)) // If allowed 266 return ACTION_VALID; 267 else return ACTION_INVALID; 268 } 269 270 // Compute the full command line to add and if non-trivial 271 // prepend the string prepend to final command line 272 // Assume cmdline points to buffer long enough to hold answer 273 void gencommand(pt_menuitem mi, char *cmdline) 274 { 275 pt_xtra x; 276 cmdline[0] = '\0'; 277 strcat(cmdline,mi->data); 278 x = (pt_xtra) mi->extra_data; 279 if ( (x) && (x->argsmenu)) gen_append_line(x->argsmenu,cmdline); 280 } 281 282 283 // run the given command together with additional options which may need passing 284 void runcommand(pt_menuitem mi) 285 { 286 char *line; 287 pt_xtra x; 288 long ipappend; 289 290 line = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH); 291 gencommand(mi,line); 292 x = (pt_xtra) mi->extra_data; 293 ipappend = (x ? x->ipappend : 0); 294 295 runsyslinuximage(line,ipappend); 296 free(line); 297 } 298 299 // set the extra info for the specified menu item. 300 void set_xtra(pt_menuitem mi, const char *argsmenu, const char *perms, unsigned int helpid, long ipappend) 301 { 302 pt_xtra xtra; 303 int bad_argsmenu, bad_perms, bad_ipappend; 304 305 mi->extra_data = NULL; // initalize 306 mi->helpid = helpid; // set help id 307 308 if (mi->action != OPT_RUN) return; 309 310 bad_argsmenu = bad_perms = bad_ipappend = 0; 311 if ( (argsmenu==NULL) || (strlen(argsmenu)==0)) bad_argsmenu = 1; 312 if ( (perms==NULL) || (strlen(perms)==0)) bad_perms = 1; 313 if ( ipappend==0) bad_ipappend = 1; 314 315 if (bad_argsmenu && bad_perms && bad_ipappend) return; 316 317 xtra = (pt_xtra) malloc(sizeof(t_xtra)); 318 mi->extra_data = (void *) xtra; 319 xtra->argsmenu = xtra->perms = NULL; 320 xtra->ipappend = ipappend; 321 if (!bad_argsmenu) { 322 xtra->argsmenu = (char *) malloc(sizeof(char)*(strlen(argsmenu)+1)); 323 strcpy(xtra->argsmenu,argsmenu); 324 } 325 if (!bad_perms) { 326 xtra->perms = (char *) malloc(sizeof(char)*(strlen(perms)+1)); 327 strcpy(xtra->perms,perms); 328 mi->handler = &check_perms; 329 } 330 } 331 332 int main(void) 333 { 334 pt_menuitem curr; 335 char quit; 336 char exitcmd[MAX_CMD_LINE_LENGTH]; 337 char exitcmdroot[MAX_CMD_LINE_LENGTH]; 338 char onerrcmd[MAX_CMD_LINE_LENGTH]; 339 char startfile[MAX_CMD_LINE_LENGTH]; 340 char *ecmd; // effective exit command or onerrorcmd 341 char skipbits; 342 char skipcmd[MAX_CMD_LINE_LENGTH]; 343 int timeout; // time in multiples of 0.1 seconds 344 int totaltimeout; // time in multiples of 0.1 seconds 345 t_dotcmd dotrv; // to store the return value of execdotcmd 346 int temp; 347 348 strcpy(username,GUEST_USER); 349 /* ---- Initializing menu system parameters --- */ 350 vmode = 0xFF; 351 skipbits = SHIFT_PRESSED | CAPSLOCK_ON; 352 PWD_ROW = 23; 353 EDIT_ROW = 23; 354 strcpy(onerrcmd,".beep 2 % % .help hlp00025.txt % .exit"); 355 strcpy(exitcmd,".exit"); 356 strcpy(exitcmdroot,""); 357 // If not specified exitcmdroot = exitcmd 358 if (exitcmdroot[0] == '\0') strcpy(exitcmdroot,exitcmd); 359 // Timeout stuff 360 timeout = 600; 361 strcpy(timeoutcmd,".wait"); 362 totaltimeout = 0; 363 strcpy(totaltimeoutcmd,"chain.c32 hd 0"); 364 strcpy(startfile,"hlp00026.txt"); 365 366 init_help("/isolinux/help"); 367 init_passwords("/isolinux/password"); 368 init_menusystem(" COMBOOT Menu System "); 369 set_window_size(1,1,21,79); 370 371 // Register the ontimeout handler, with a time out of 10 seconds 372 reg_ontimeout(ontimeout,timeout*10,0); 373 reg_ontotaltimeout(ontotaltimeout,totaltimeout*10); 374 375 // Register menusystem handlers 376 reg_handler(HDLR_KEYS,&keys_handler); 377 /* ---- End of initialization --- */ 378 379 /* ------- MENU netmenu ----- */ 380 add_named_menu("netmenu"," Init Network ",-1); 381 382 curr = add_item("<N>one","Dont start network",OPT_RADIOITEM,"network=no",0); 383 set_xtra(curr,"","",65535,0); // Set associated extra info 384 set_shortcut(-1); 385 386 curr = add_item("<d>hcp","Use DHCP",OPT_RADIOITEM,"network=dhcp",0); 387 set_xtra(curr,"","",65535,0); // Set associated extra info 388 set_shortcut(-1); 389 390 /* ------- MENU testing ----- */ 391 add_named_menu("testing"," Testing ",-1); 392 393 curr = add_item("<M>emory Test","Perform extensive memory testing",OPT_RUN,"memtest",0); 394 set_xtra(curr,"","",25,3); // Set associated extra info 395 set_shortcut(-1); 396 397 curr = add_item("<I>nvisible","You dont see this",OPT_INVISIBLE,"",0); 398 set_xtra(curr,"","",65535,0); // Set associated extra info 399 set_shortcut(-1); 400 401 curr = add_item("<E>xit menu","Go one level up",OPT_EXITMENU,"",0); 402 set_xtra(curr,"","",65535,0); // Set associated extra info 403 set_shortcut(-1); 404 405 /* ------- MENU rescue ----- */ 406 add_named_menu("rescue"," Rescue Options ",-1); 407 408 curr = add_item("<L>inux Rescue","Run linresc",OPT_RUN,"linresc",0); 409 set_xtra(curr,"","",65535,0); // Set associated extra info 410 set_shortcut(-1); 411 412 curr = add_item("<D>os Rescue","dosresc",OPT_RUN,"dosresc",0); 413 set_xtra(curr,"","",65535,0); // Set associated extra info 414 set_shortcut(-1); 415 416 curr = add_item("<W>indows Rescue","winresc",OPT_RUN,"winresc",0); 417 set_xtra(curr,"","",65535,0); // Set associated extra info 418 set_shortcut(-1); 419 420 curr = add_item("<E>xit this menu","Go one level up",OPT_EXITMENU,"",0); 421 set_xtra(curr,"","",65535,0); // Set associated extra info 422 set_shortcut(-1); 423 424 /* ------- MENU prep ----- */ 425 add_named_menu("prep"," Prep options ",-1); 426 427 curr = add_item("<b>aseurl by IP?","Specify gui baseurl by IP address",OPT_CHECKBOX,"baseurl=http://192.168.0.1",0); 428 set_xtra(curr,"","",65535,0); // Set associated extra info 429 set_shortcut(-1); 430 431 curr = add_item("<m>ountcd?","Mount the cdrom drive?",OPT_CHECKBOX,"mountcd",0); 432 set_xtra(curr,"","",65535,0); // Set associated extra info 433 set_shortcut(-1); 434 435 curr = add_item("Network Initialization","How to initialise network device?",OPT_RADIOMENU,"netmenu",0); 436 set_xtra(curr,"","",65535,0); // Set associated extra info 437 set_shortcut(-1); 438 439 curr = add_item("","",OPT_SEP,"",0); 440 set_xtra(curr,"","",65535,0); // Set associated extra info 441 set_shortcut(-1); 442 443 curr = add_item("Reinstall <w>indows","Re-install the windows side of a dual boot setup",OPT_CHECKBOX,"repair=win",0); 444 set_xtra(curr,"","",65535,0); // Set associated extra info 445 set_shortcut(-1); 446 447 curr = add_item("Reinstall <l>inux","Re-install the linux side of a dual boot setup",OPT_CHECKBOX,"repair=lin",0); 448 set_xtra(curr,"","",65535,0); // Set associated extra info 449 set_shortcut(-1); 450 451 curr = add_item("","",OPT_SEP,"",0); 452 set_xtra(curr,"","",65535,0); // Set associated extra info 453 set_shortcut(-1); 454 455 curr = add_item("<R>un prep now","Execute prep with the above options",OPT_RUN,"prep",0); 456 set_xtra(curr,"prep","",65535,0); // Set associated extra info 457 set_shortcut(-1); 458 459 curr = add_item("<E>xit this menu","Go up one level",OPT_EXITMENU,"",0); 460 set_xtra(curr,"","",65535,0); // Set associated extra info 461 set_shortcut(-1); 462 463 /* ------- MENU main ----- */ 464 add_named_menu("main"," Main Menu ",-1); 465 466 curr = add_item(loginstr,"Login/Logout of authentication system",OPT_RUN,NULL,0); 467 curr->helpid = 65535; 468 curr->handler = &login_handler; 469 470 curr = add_item("<P>repare","prep",OPT_RUN,"prep",0); 471 set_xtra(curr,"","",65535,0); // Set associated extra info 472 set_shortcut(-1); 473 474 curr = add_item("<P>rep options...","Options for prep",OPT_SUBMENU,"prep",0); 475 set_xtra(curr,"","",65535,0); // Set associated extra info 476 set_shortcut(-1); 477 478 curr = add_item("<R>escue options...","Troubleshoot a system",OPT_SUBMENU,"rescue",0); 479 set_xtra(curr,"","",26,0); // Set associated extra info 480 set_shortcut(-1); 481 482 curr = add_item("<T>esting...","Options to test hardware",OPT_SUBMENU,"testing",0); 483 set_xtra(curr,"","",65535,0); // Set associated extra info 484 set_shortcut(-1); 485 486 curr = add_item("<E>xit to prompt","Exit the menu system",OPT_EXITMENU,"",0); 487 set_xtra(curr,"","",65535,0); // Set associated extra info 488 set_shortcut(-1); 489 /* ------- END OF MENU declarations ----- */ 490 491 // Check if we should skip the menu altogether 492 quit = 0; // Dont skip the menu 493 if (getshiftflags() & skipbits) { // we must skip the menu altogther and execute skipcmd 494 dotrv = execdotcmd(skipcmd,".beep%.exit",NULL); // Worst case we beep and exit 495 if (dotrv == QUIT_CMD) quit = 1; 496 } 497 498 // Switch vide mode if required 499 if (vmode != 0xFF) setvideomode(vmode); 500 501 // Do we have a startfile to display? 502 if (startfile[0] != '\0') runhelp(startfile); 503 504 // The main loop 505 while (quit == 0) { // As long as quit is zero repeat 506 curr = showmenus(find_menu_num("main")); // Initial menu is the one called "main" 507 508 if (curr) { 509 if (curr->action == OPT_RUN) { 510 ecmd = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH); 511 gencommand(curr,ecmd); 512 temp = (curr->extra_data ? ((pt_xtra)curr->extra_data)->ipappend : 0); 513 runsyslinuximage(ecmd,temp); 514 // kernel not found so execute the appropriate dot command 515 dotrv = execdotcmd(onerrcmd,".quit",ecmd); // pass bad cmdline as arg 516 if (dotrv== QUIT_CMD) quit = 1; 517 free(ecmd); ecmd = NULL; 518 } 519 else csprint("Error in programming!",0x07); 520 } else { 521 // find effective exit command 522 ecmd = ( isallowed(username,"root") ? exitcmdroot : exitcmd); 523 dotrv = execdotcmd(ecmd,".repeat",NULL); 524 quit = (dotrv == QUIT_CMD ? 1 : 0); // should we exit now 525 } 526 } 527 528 // Deallocate space used and quit 529 close_passwords(); 530 close_help(); 531 close_menusystem(); 532 return 0; 533 } 534 535