#include #include #include #include #include #include #include #include #include "askrunlevel.h" #include #include "../paths.h" #include "askrunlevel.m" #include static HELP_FILE help_boot_log (HELP_ASKRUN,"bootlog"); static CONFIG_FILE f_boot_log (VAR_LOG_BOOT_LOG ,help_boot_log ,CONFIGF_OPTIONAL|CONFIGF_MANAGED); static const char bootlog_key[]="#########"; /* Store the boot message in /var/adm/boot.log */ void boot_save2log() { /* #Specification: askrunlevel / boot log At each boot, askrunlevel grab the log (/proc/kmsg) and stores it in /var/adm/boot.log. askrunlevel can present these logs to the user later. For this reason, you won't find this information in /var/adm/messages like a normal linux. */ FILE_CFG *fout = f_boot_log.fopen ("a"); if (fout != NULL){ { time_t tim = time(NULL); const char *datestr = asctime(localtime(&tim)); fprintf (fout,"%s %s\n",bootlog_key,datestr); } int fin = open ("/proc/kmsg",O_RDONLY|O_NDELAY); if (fin != -1){ fd_set set; FD_ZERO (&set); FD_SET (fin,&set); struct timeval timeout; timeout.tv_usec = timeout.tv_sec = 0; if (select(fin+1,&set,NULL,NULL,&timeout)>0){ char buf[5000]; int nb = read (fin,buf,sizeof(buf)-1); if (nb >= 0){ buf[nb] = '\0'; if (fout != NULL){ fputs (buf,fout); } } } close (fin); } fclose (fout); } } /* Locate all boot intro or a specific log in the log file if choice == -1, get all intro if choice != -1. get one log */ static int boot_getlist( CONFIG_FILE &fcfg, const char *dateprefixs[], SSTRINGS &lst, int choice) { FILE_CFG *fin = fcfg.fopen ("r"); if (fin != NULL){ char buf[300]; int collect = 0; int nbboot = 0; int sizekeys[20]; for (int k=0; dateprefixs[k] != NULL; k++){ sizekeys[k] = strlen(dateprefixs[k]); } while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ strip_end (buf); int prefix = 0; int sizekey = 0; for (int i=0; dateprefixs[i] != NULL; i++){ if (strncmp(buf,dateprefixs[i],sizekeys[i])==0){ prefix = 1; sizekey = sizekeys[i]; break; } } if (prefix){ if (choice == -1){ lst.add (new SSTRING (buf+sizekey+1)); }else if (choice == nbboot){ collect = 1; }else{ collect = 0; } nbboot++; }else if (collect){ lst.add (new SSTRING (buf)); } } fclose (fin); } return lst.getnb(); } static void boot_showonelog ( CONFIG_FILE &fcfg, // Log file to read const char *dateprefixs[], // Prefix to identify session lines SSTRINGS &lst, int choice) { SSTRINGS onelog; if (boot_getlist(fcfg,dateprefixs,onelog,choice)==0){ xconf_error (MSG_U(E_EMPTYLOG,"Empty log")); }else{ dialog_textbox (lst.getitem(choice)->get(),onelog); } } /* Present the logs in a linuxconf log file */ void boot_showlog ( CONFIG_FILE &fcfg, // Log file to read const char *dateprefixs[], // Prefix to identify session lines const char *title, const char *intro, HELP_FILE &help) { SSTRINGS lst; int nb = boot_getlist(fcfg,dateprefixs,lst,-1); if (nb == 0){ xconf_error (MSG_U(E_NOLOG,"No log available")); }else{ int choice = nb - 1; DIALOG_RECORDS dia; dia.newf_head ("",MSG_U(H_LOGS,"Date\tAction")); for (int i=0; iget(); char buf[strlen(s)+1]; strcpy (buf,s); // Older logs where formatting the date followed by the description // without any way to tell them apart. Newer are using a TAB. char *tab = strchr(buf,'\t'); if (tab != NULL){ *tab++ = '\0'; }else{ buf[25] = '\0'; tab = buf+26; } dia.new_menuitem(buf,tab); } while (1){ MENU_STATUS code = dia.editmenu (title,intro,help,choice,0); if (code == MENU_OK){ boot_showonelog (fcfg,dateprefixs,lst,choice); }else{ break; } } } } /* Present the last log in a linuxconf log file */ void boot_showlastlog ( CONFIG_FILE &fcfg, // Log file to read const char *dateprefixs[]) // Prefix to identify session lines { SSTRINGS lst; int nb = boot_getlist(fcfg,dateprefixs,lst,-1); if (nb == 0){ xconf_error (MSG_R(E_NOLOG)); }else{ boot_showonelog (fcfg,dateprefixs,lst,nb-1); } } /* Present the logs of the last boots */ void boot_showlog () { const char *tb[]={bootlog_key,NULL}; boot_showlog (f_boot_log,tb ,MSG_U(T_BOOTLOG,"boot log") ,MSG_U(I_BOOTLOG ,"These are the recording of the previous\n" "boot of this machine") ,help_boot_log); }