Home | History | Annotate | Download | only in cmenu
      1 All the lines in this file not in between --something BEGINS-- and --something ENDS--
      2 is ignored completely and will not make it into the generated C file
      3 
      4 This file has sections of C code each section delimited by --secname BEGINS--
      5 and --secname ENDS--. In the generated C code certain section may be used multiple
      6 times. Currently the different section which must be defined are
      7 
      8 header, system, item, login and footer
      9 
     10 Any additional sections you define will be processed but will probably not make it
     11 to the C code if you do not modify menugen.py to use it.
     12 
     13 header and footer go through unmolested. The remaining are % substituted using
     14 python rules. Basically it means %(var)s gets replaced by the value of the variable
     15 "var" which is a processed form of what is read from the .menu file
     16 
     17 NOTE: There is absolutely no C code in the python script, so you are free to
     18 modify this template to suit your needs
     19 
     20 --header BEGINS--
     21 /* -*- c -*- ------------------------------------------------------------- *
     22  *
     23  *   Copyright 2004-2006 Murali Krishnan Ganapathy - All Rights Reserved
     24  *
     25  *   This program is free software; you can redistribute it and/or modify
     26  *   it under the terms of the GNU General Public License as published by
     27  *   the Free Software Foundation, Inc., 53 Temple Place Ste 330,
     28  *   Boston MA 02111-1307, USA; either version 2 of the License, or
     29  *   (at your option) any later version; incorporated herein by reference.
     30  *
     31  * ----------------------------------------------------------------------- */
     32 
     33 #ifndef NULL
     34 #define NULL ((void *) 0)
     35 #endif
     36 
     37 #include "cmenu.h"
     38 #include "help.h"
     39 #include "passwords.h"
     40 #include "com32io.h"
     41 #include <string.h>
     42 #include <stdlib.h>
     43 #include <unistd.h>
     44 
     45 #define MAX_CMD_LINE_LENGTH 514
     46 
     47 typedef struct s_xtra {
     48   long ipappend; // Stores the ipappend flag to send (useful for PXELINUX only)
     49   char *argsmenu; // Stores the name of menu which contains options for the given RUN item
     50   char *perms; // stores the permissions required to activate the item
     51 } t_xtra;
     52 
     53 typedef t_xtra *pt_xtra; // Pointer to extra datastructure
     54 
     55 // Types of dot commands for which caller takes responsibility of handling
     56 // In some case some commands may not make sense, it is up to the caller
     57 // to handle cases which do not make sense
     58 typedef enum {QUIT_CMD, REPEAT_CMD, ENTER_CMD, ESCAPE_CMD} t_dotcmd;
     59 
     60 
     61 /*----------------- Global Variables */
     62 
     63 // default user
     64 #define GUEST_USER "guest"
     65 
     66 // for local commands. return value of execdotcmd
     67 #define QUIT_CMD 0
     68 #define RPT_CMD 1
     69 
     70 char username[12]; // Name of user currently using the system
     71 
     72 int PWD_ROW; // Line number where user authentication happens
     73 int EDIT_ROW; // row where User Tab
     74 
     75 char loginstr[] = "<L>ogin  ";
     76 char logoutstr[30];
     77 
     78 int vmode; // The video mode we want to be in
     79 char timeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on timeout
     80 char totaltimeoutcmd[MAX_CMD_LINE_LENGTH]; // Command to execute on totaltimeout
     81 
     82 char QUITSTR[] = ".quit"; // same as exit
     83 char IGNORESTR[]=".ignore"; // same as repeat, wait
     84 
     85 /*----------------  End globals */
     86 
     87 // returns pointer to first non-space char
     88 // and advances end of str by removing trailing spaces
     89 char * strip(char *str)
     90 {
     91   char *p,*s,*e;
     92   if (!str) return NULL;
     93   p = str;
     94   s = NULL;
     95   e = NULL;
     96   while (*p) {
     97     if (*p != ' ') {
     98        // mark start of string or record the last visited non-space char
     99        if (!s) s=p; else e=p;
    100     }
    101     p++;
    102   }
    103   *(++e)='\0'; // kill string earlier
    104   return s;
    105 }
    106 
    107 // executes a list of % separated commands
    108 // non-dot commands are assumed to be syslinux commands
    109 // All syslinux commands are appended with the contents of kerargs
    110 // If it fails (kernel not found) then the next one is tried in the
    111 // list
    112 // returns QUIT_CMD or RPT_CMD
    113 t_dotcmd execdotcmd(const char *cmd, char *defcmd, const char *kerargs)
    114 {
    115    char cmdline[MAX_CMD_LINE_LENGTH];
    116    char dotcmd[MAX_CMD_LINE_LENGTH];
    117    char *curr,*next,*p,*args;
    118    char ctr;
    119 
    120    strcpy(dotcmd,cmd);
    121    next = dotcmd;
    122    cmdline[0] = '\0';
    123    while (*next) { // if something to do
    124       curr = next;
    125       p = strchr(next,'%');
    126       if (p) {
    127          *p--='\0'; next=p+2;
    128          while (*p == ' ') p--;
    129          *(++p)='\0'; // remove trailing spaces
    130       } else {
    131         if (*defcmd) { // execute defcmd next
    132             next=defcmd;
    133             defcmd=NULL; // exec def cmd only once
    134         } else next=NULL;
    135       }
    136       // now we just need to execute the command "curr"
    137       curr = strip(curr);
    138       if (curr[0] != '.') { // just run the kernel
    139          strcpy(cmdline,curr);
    140          if (kerargs) strcat(cmdline,kerargs);
    141          runsyslinuximage(cmdline,0); // No IPAppend
    142       } else { // We have a DOT command
    143         // split command into command and args (may be empty)
    144         args = curr;
    145         while ( (*args != ' ') && (*args != '\0') ) args++;
    146         if (*args) { // found a space
    147            *args++ = '\0';
    148            while (*args == ' ') args++; // skip over spaces
    149         }
    150         if ( (strcmp(curr,".exit")==0) ||
    151              (strcmp(curr,".quit")==0)
    152            )
    153            return QUIT_CMD;
    154         if ( (strcmp(curr,".repeat")==0) ||
    155              (strcmp(curr,".ignore")==0) ||
    156              (strcmp(curr,".wait")==0)
    157            )
    158            return RPT_CMD;
    159         if (strcmp(curr,".beep")==0) {
    160            if ((args) && ('0' <= args[0]) && (args[0] <= '9'))
    161               ctr = args[0]-'0';
    162            else ctr=1;
    163            for (;ctr>0; ctr--) beep();
    164         }
    165         if (strcmp(curr,".help")==0) runhelp(args);
    166       }
    167    }
    168    return RPT_CMD; // by default we do not quit
    169 }
    170 
    171 
    172 TIMEOUTCODE timeout(const char *cmd)
    173 {
    174   t_dotcmd c;
    175   c = execdotcmd(cmd,".wait",NULL);
    176   switch(c) {
    177     case ENTER_CMD:
    178          return CODE_ENTER;
    179     case ESCAPE_CMD:
    180          return CODE_ESCAPE;
    181     default:
    182          return CODE_WAIT;
    183   }
    184 }
    185 
    186 TIMEOUTCODE ontimeout(void)
    187 {
    188    return timeout(timeoutcmd);
    189 }
    190 
    191 TIMEOUTCODE ontotaltimeout(void)
    192 {
    193    return timeout(totaltimeoutcmd);
    194 }
    195 
    196 void keys_handler(t_menusystem * ms __attribute__ (( unused )), t_menuitem * mi, int scancode)
    197 {
    198    int nc, nr;
    199 
    200    if (getscreensize(1, &nr, &nc)) {
    201        /* Unknown screen size? */
    202        nc = 80;
    203        nr = 24;
    204    }
    205 
    206    if ( (scancode == KEY_F1) && (mi->helpid != 0xFFFF) ) { // If scancode of F1 and non-trivial helpid
    207       runhelpsystem(mi->helpid);
    208    }
    209 
    210    // If user hit TAB, and item is an "executable" item
    211    // and user has privileges to edit it, edit it in place.
    212    if ((scancode == KEY_TAB) && (mi->action == OPT_RUN) &&
    213        (EDIT_ROW < nr) && (EDIT_ROW > 0) &&
    214        (isallowed(username,"editcmd") || isallowed(username,"root"))) {
    215      // User typed TAB and has permissions to edit command line
    216      gotoxy(EDIT_ROW,1);
    217      csprint("Command line:",0x07);
    218      editstring(mi->data,ACTIONLEN);
    219      gotoxy(EDIT_ROW,1);
    220      cprint(' ',0x07,nc-1);
    221    }
    222 }
    223 
    224 t_handler_return login_handler(t_menusystem *ms, t_menuitem *mi)
    225 {
    226   (void)mi; // Unused
    227   char pwd[40];
    228   char login[40];
    229   int nc, nr;
    230   t_handler_return rv;
    231 
    232   (void)ms;
    233 
    234   rv = ACTION_INVALID;
    235   if (PWD_ROW < 0) return rv; // No need to authenticate
    236 
    237   if (mi->item == loginstr) { /* User wants to login */
    238     if (getscreensize(1, &nr, &nc)) {
    239         /* Unknown screen size? */
    240         nc = 80;
    241         nr = 24;
    242     }
    243 
    244     gotoxy(PWD_ROW,1);
    245     csprint("Enter Username: ",0x07);
    246     getstring(login, sizeof username);
    247     gotoxy(PWD_ROW,1);
    248     cprint(' ',0x07,nc);
    249     csprint("Enter Password: ",0x07);
    250     getpwd(pwd, sizeof pwd);
    251     gotoxy(PWD_ROW,1);
    252     cprint(' ',0x07,nc);
    253 
    254     if (authenticate_user(login,pwd))
    255     {
    256       strcpy(username,login);
    257       strcpy(logoutstr,"<L>ogout ");
    258       strcat(logoutstr,username);
    259       mi->item = logoutstr; // Change item to read "Logout"
    260       rv.refresh = 1; // refresh the screen (as item contents changed)
    261     }
    262     else strcpy(username,GUEST_USER);
    263   }
    264   else // User needs to logout
    265   {
    266     strcpy(username,GUEST_USER);
    267     strcpy(logoutstr,"");
    268     mi->item = loginstr;
    269   }
    270 
    271   return rv;
    272 }
    273 
    274 t_handler_return check_perms(t_menusystem *ms, t_menuitem *mi)
    275 {
    276    char *perms;
    277    pt_xtra x;
    278 
    279    (void) ms; // To keep compiler happy
    280 
    281    x = (pt_xtra) mi->extra_data;
    282    perms = ( x ? x->perms : NULL);
    283    if (!perms) return ACTION_VALID;
    284 
    285    if (isallowed(username,"root") || isallowed(username,perms)) // If allowed
    286       return ACTION_VALID;
    287    else return ACTION_INVALID;
    288 }
    289 
    290 // Compute the full command line to add and if non-trivial
    291 // prepend the string prepend to final command line
    292 // Assume cmdline points to buffer long enough to hold answer
    293 void gencommand(pt_menuitem mi, char *cmdline)
    294 {
    295    pt_xtra x;
    296    cmdline[0] = '\0';
    297    strcat(cmdline,mi->data);
    298    x = (pt_xtra) mi->extra_data;
    299    if ( (x) && (x->argsmenu)) gen_append_line(x->argsmenu,cmdline);
    300 }
    301 
    302 
    303 // run the given command together with additional options which may need passing
    304 void runcommand(pt_menuitem mi)
    305 {
    306    char *line;
    307    pt_xtra x;
    308    long ipappend;
    309 
    310    line = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH);
    311    gencommand(mi,line);
    312    x = (pt_xtra) mi->extra_data;
    313    ipappend = (x ? x->ipappend : 0);
    314 
    315    runsyslinuximage(line,ipappend);
    316    free(line);
    317 }
    318 
    319 // set the extra info for the specified menu item.
    320 void set_xtra(pt_menuitem mi, const char *argsmenu, const char *perms, unsigned int helpid, long ipappend)
    321 {
    322    pt_xtra xtra;
    323    int bad_argsmenu, bad_perms, bad_ipappend;
    324 
    325    mi->extra_data = NULL; // initalize
    326    mi->helpid = helpid; // set help id
    327 
    328    if (mi->action != OPT_RUN) return;
    329 
    330    bad_argsmenu = bad_perms = bad_ipappend = 0;
    331    if ( (argsmenu==NULL) || (strlen(argsmenu)==0)) bad_argsmenu = 1;
    332    if ( (perms==NULL) || (strlen(perms)==0)) bad_perms = 1;
    333    if ( ipappend==0) bad_ipappend = 1;
    334 
    335    if (bad_argsmenu && bad_perms && bad_ipappend) return;
    336 
    337    xtra = (pt_xtra) malloc(sizeof(t_xtra));
    338    mi->extra_data = (void *) xtra;
    339    xtra->argsmenu = xtra->perms = NULL;
    340    xtra->ipappend = ipappend;
    341    if (!bad_argsmenu) {
    342       xtra->argsmenu = (char *) malloc(sizeof(char)*(strlen(argsmenu)+1));
    343       strcpy(xtra->argsmenu,argsmenu);
    344    }
    345    if (!bad_perms) {
    346       xtra->perms = (char *) malloc(sizeof(char)*(strlen(perms)+1));
    347       strcpy(xtra->perms,perms);
    348       mi->handler = &check_perms;
    349    }
    350 }
    351 
    352 int main(void)
    353 {
    354   pt_menuitem curr;
    355   char quit;
    356   char exitcmd[MAX_CMD_LINE_LENGTH];
    357   char exitcmdroot[MAX_CMD_LINE_LENGTH];
    358   char onerrcmd[MAX_CMD_LINE_LENGTH];
    359   char startfile[MAX_CMD_LINE_LENGTH];
    360   char *ecmd; // effective exit command or onerrorcmd
    361   char skipbits;
    362   char skipcmd[MAX_CMD_LINE_LENGTH];
    363   int timeout; // time in multiples of 0.1 seconds
    364   int totaltimeout; // time in multiples of 0.1 seconds
    365   t_dotcmd dotrv; // to store the return value of execdotcmd
    366   int temp;
    367 
    368   strcpy(username,GUEST_USER);
    369 --header ENDS--
    370 --system BEGINS--
    371 /* ---- Initializing menu system parameters --- */
    372   vmode = %(videomode)s;
    373   skipbits = %(skipcondn)s;
    374   PWD_ROW = %(pwdrow)s;
    375   EDIT_ROW = %(editrow)s;
    376   strcpy(onerrcmd,"%(onerrorcmd)s");
    377   strcpy(exitcmd,"%(exitcmd)s");
    378   strcpy(exitcmdroot,"%(exitcmdroot)s");
    379   // If not specified exitcmdroot = exitcmd
    380   if (exitcmdroot[0] == '\0') strcpy(exitcmdroot,exitcmd);
    381   // Timeout stuff
    382   timeout = %(timeout)s;
    383   strcpy(timeoutcmd,"%(timeoutcmd)s");
    384   totaltimeout = %(totaltimeout)s;
    385   strcpy(totaltimeoutcmd,"%(totaltimeoutcmd)s");
    386   strcpy(startfile,"%(startfile)s");
    387 
    388   init_help("%(helpdir)s");
    389   init_passwords("%(pwdfile)s");
    390   init_menusystem("%(title)s");
    391   set_window_size(%(top)s,%(left)s,%(bot)s,%(right)s);
    392 
    393   // Register the ontimeout handler, with a time out of 10 seconds
    394   reg_ontimeout(ontimeout,timeout*10,0);
    395   reg_ontotaltimeout(ontotaltimeout,totaltimeout*10);
    396 
    397   // Register menusystem handlers
    398   reg_handler(HDLR_KEYS,&keys_handler);
    399 /* ---- End of initialization --- */
    400 --system ENDS--
    401 --item BEGINS--
    402 
    403   curr = add_item("%(item)s","%(info)s",%(type)s,"%(data)s",%(state)d);
    404   set_xtra(curr,"%(argsmenu)s","%(perms)s",%(helpid)d,%(ipappend)d); // Set associated extra info
    405   set_shortcut(%(shortcut)s);
    406 --item ENDS--
    407 --login BEGINS--
    408 
    409   curr = add_item(loginstr,"Login/Logout of authentication system",OPT_RUN,NULL,0);
    410   curr->helpid = %(helpid)d;
    411   curr->handler = &login_handler;
    412 --login ENDS--
    413 --menu BEGINS--
    414 
    415 /* ------- MENU %(name)s ----- */
    416   add_named_menu("%(name)s","%(title)s",-1);
    417 --menu ENDS--
    418 --footer BEGINS--
    419 /* ------- END OF MENU declarations ----- */
    420 
    421 // Check if we should skip the menu altogether
    422   quit = 0; // Dont skip the menu
    423   if (getshiftflags() & skipbits) { // we must skip the menu altogther and execute skipcmd
    424     dotrv = execdotcmd(skipcmd,".beep%.exit",NULL); // Worst case we beep and exit
    425     if (dotrv == QUIT_CMD) quit = 1;
    426   }
    427 
    428 // Switch vide mode if required
    429    if (vmode != 0xFF) setvideomode(vmode);
    430 
    431 // Do we have a startfile to display?
    432    if (startfile[0] != '\0') runhelp(startfile);
    433 
    434 // The main loop
    435   while (quit == 0) { // As long as quit is zero repeat
    436      curr = showmenus(find_menu_num("main")); // Initial menu is the one called "main"
    437 
    438      if (curr) {
    439         if (curr->action == OPT_RUN) {
    440            ecmd = (char *)malloc(sizeof(char)*MAX_CMD_LINE_LENGTH);
    441            gencommand(curr,ecmd);
    442            temp = (curr->extra_data ? ((pt_xtra)curr->extra_data)->ipappend : 0);
    443            runsyslinuximage(ecmd,temp);
    444            // kernel not found so execute the appropriate dot command
    445            dotrv = execdotcmd(onerrcmd,".quit",ecmd); // pass bad cmdline as arg
    446            if (dotrv== QUIT_CMD) quit = 1;
    447            free(ecmd); ecmd = NULL;
    448         }
    449         else csprint("Error in programming!",0x07);
    450      } else {
    451         // find effective exit command
    452         ecmd = ( isallowed(username,"root") ? exitcmdroot : exitcmd);
    453         dotrv = execdotcmd(ecmd,".repeat",NULL);
    454         quit = (dotrv == QUIT_CMD ? 1 : 0); // should we exit now
    455      }
    456   }
    457 
    458 // Deallocate space used and quit
    459   close_passwords();
    460   close_help();
    461   close_menusystem();
    462   return 0;
    463 }
    464 
    465 --footer ENDS--
    466