#include #include #include #include #include #include #include #include #include "netconf.h" #include "netconf.m" #include "../askrunlevel/askrunlevel.h" #include static HELP_FILE help_netconf_log (HELP_NETCONF,"netconflog"); static CONFIG_FILE f_netconf_log (VAR_LOG_NETCONF_LOG ,help_netconf_log ,CONFIGF_OPTIONAL|CONFIGF_MANAGED|CONFIGF_FIXEDBASE ,"root","root",0600); static const char *tbargs[]={"message",NULL}; static MESSAGE_DEF msglog ("netconf.log",tbargs); static int netlog_mask=-1; // The default is to show everything /* Return != 0 if str is a valid ip number (lexically) */ int net_isipnum(const char *str) { int ret = 0; int nbpt = 0; // Number of period met while (1){ if (!isdigit(*str)){ break; }else{ int num = atoi(str); while (isdigit(*str)) str++; if (num > 255){ break; }else if (*str == '\0'){ ret = 1; break; }else if (*str != '.'){ break; }else{ nbpt++; str++; } } } if (ret && nbpt != 3) ret = 0; return ret; } static const char BOOT[]="BOOT"; static const char VERBOSE[]="verbose"; static bool net_show = true; /* Control if the output of commands and other stuff is sent to the display. This is especially used while probing the system to find out if there is work to do. The idea is that the same routine which does the work is called to check if there is work to do. In both cases, the routing spits a lot of stuff. */ EXPORT bool net_setshowmode (bool mode) { bool old = net_show; net_show = mode; return old; } static int nberr=0; /* Reset the error counter */ EXPORT void net_resetnberr() { nberr = 0; } /* Return the current value of the error counter */ EXPORT int net_getnberr() { return nberr; } /* Get the configuration of the log print setting */ int net_getlogmask() { static char netmask_loaded = 0; if (!netmask_loaded){ netmask_loaded = 1; netlog_mask = linuxconf_getvalnum (BOOT,VERBOSE,netlog_mask); } return netlog_mask; } /* Set the configuration of the log print setting */ int net_setlogmask(int mask) { netlog_mask = mask; linuxconf_replace (BOOT,VERBOSE,netlog_mask); return linuxconf_save(); } static void net_putlog (int level, const char *buf) { if (simul_ison()){ if (!simul_ishint() && (level == NETLOG_REQ || level == NETLOG_CMD || level == NETLOG_WHY)){ simul_addmsg (buf); } }else{ net_getlogmask(); if (level == NETLOG_ERR) nberr++; if ((level & netlog_mask) != 0 && net_show){ dialog_consout ("%s",buf); } FILE_CFG *fout = f_netconf_log.fopen ("a"); static char shown_err = 0; /* #Specification: /usr/adm/netconf.log / can't open Action taken by netconf are log in /var/log/netconf.log. They can't be log with syslogd because syslogd is started by netconf and may not be available. If the file can't be open, one and only one error message will be shown (per netconf session). */ if (fout != NULL){ fputs (buf,fout); fclose (fout); const char *args[]={buf,NULL}; module_sendmessage (msglog,1,args); }else if (!shown_err){ shown_err = 1; xconf_error (MSG_U(E_CANTOPEN,"Can't open file %s\n(%s)\n") ,f_netconf_log.getpath(),strerror(errno)); } } } EXPORT void net_hint (const char *var, const char *value, ...) { if (simul_ishint()){ va_list list; va_start (list,value); printf ("%s=\"",var); vprintf (value,list); printf ("\"\n"); va_end (list); } } static bool net_printhintok = true; static bool net_somehints=false; /* Record if we should enable net_printhint */ void net_enableprinthint (bool mode) { net_printhintok = mode; net_somehints = false; } /* Return true if there was at least one call to net_printhint */ bool net_washints () { return net_somehints; } /* Send output to stdout if in hinting mode. Record that there was one hint sent. net_washints() report this fact. */ void net_printhint (const char *str, ...) { if (net_printhintok){ if (simul_ishint()){ va_list list; va_start (list,str); vprintf (str,list); va_end (list); } } net_somehints=true; } /* Add a message in /usr/adm/netconf.log */ void net_prtlog (const char *ctl, ...) { char buf[10000]; va_list list; va_start (list,ctl); vsnprintf (buf,sizeof(buf)-1,ctl,list); va_end (list); net_putlog (NETLOG_REQ,buf); } static bool net_intro_done = false; EXPORT void net_prtlog (int level, const char *ctl, ...) { if (!net_intro_done) net_introlog (NETINTRO_MISC); char buf[10000]; char *ptbuf = buf; memset (buf,' ',20); if (level == NETLOG_TITLE){ ptbuf += 2; }else if (level == NETLOG_ERR){ ptbuf+=8; *ptbuf++ = '*'; ptbuf++; }else if (level == NETLOG_OUT){ ptbuf+=8; *ptbuf++ = '>'; ptbuf++; }else if (level == NETLOG_VERB){ ptbuf+=8; *ptbuf++ = '!'; ptbuf++; }else if (level == NETLOG_CMD){ ptbuf += 6; }else if (level == NETLOG_WHY){ ptbuf += 4; *ptbuf++ = '?'; ptbuf++; } va_list list; va_start (list,ctl); vsnprintf (ptbuf,sizeof(buf)-10,ctl,list); va_end (list); net_putlog (level,buf); } static const char *tbhead[]={ "### Pre-booting", "### booting", "### fixperm", "netconf --update", "### switch runlevel", "### ppp postcon", "### ppp diald", "### Archiving configs", "### Extracting configs", "### Switching configs", "### Publish tree", "### Import group", "### Creating user account", "### Deleting user account", "### Updating user account", "### Changing service activity", "### misc", NULL }; /* Send a title string with a date in /var/adm/netconf.log */ EXPORT void net_introlog (int msg) { FILE_CFG *fout = f_netconf_log.fopen ("a"); if (fout != NULL){ // Don't forget to update tbhead above so it matches tbinfo[] static const char *tbinfo[]={ MSG_U(I_PREBOOT,"Tasks before booting"), MSG_U(I_BOOTING,"Booting"), MSG_U(I_FIXPERM,"Fixperm session"), MSG_U(I_UPDATE,"Activating changes"), MSG_U(I_RUNLEVEL,"Switching runlevel"), MSG_U(I_PPPPOSTCON,"PPP postconnect commands"), MSG_U(I_PPPDIALD,"PPP diald setup commands"), MSG_U(I_ARCHIVE,"Configuration archiving"), MSG_U(I_EXTRACT,"Configuration extraction"), MSG_U(I_SWITCHCONF,"Switching configuration"), MSG_U(I_PUBLISH,"Publish an admin tree"), MSG_U(I_IMPORT,"Import an admin group"), MSG_U(I_CREATEUSER,"Creating user account"), MSG_U(I_DELETEUSER,"Deleting user account"), MSG_U(I_MODIFYUSER,"Updating user account"), MSG_U(I_CHANGINGSERVICES,"Turning services on and off"), MSG_U(I_MISC,"Miscellaneous task"), NULL }; time_t ti = time(NULL); char bufdate[100]; strcpy (bufdate,asctime(localtime(&ti))); strip_end (bufdate); fprintf (fout, "%s: %s\t%s\n" ,tbhead[msg] ,bufdate ,tbinfo[msg]); fclose (fout); net_intro_done = true; } } /* Log the title of a set of configuration commands */ EXPORT void net_title (const char *msg) { net_prtlog (NETLOG_TITLE,"%s\n",msg); } /* Log the title of a major configuration section. */ EXPORT void net_section (const char *msg) { net_prtlog (NETLOG_SECTION,"%s\n",msg); } /* Show all entries in the linuxconf logs (/var/log/netconf.log) */ EXPORT void net_showlog () { boot_showlog (f_netconf_log,tbhead ,MSG_U(T_CONFIGLOG,"Configuration log") ,MSG_U(I_CONFIGLOG ,"These logs shows all configuration commands\n" "issued by linuxconf") ,help_netconf_log); } /* Show only the last entry in the linuxconf logs (/var/log/netconf.log) */ EXPORT void net_showlastlog () { boot_showlastlog (f_netconf_log,tbhead); } #ifdef TEST static void test (const char *str) { printf ("testing %s -> %s\n",str ,net_isipnum(str) ? "OK" : "Not valid"); } int main(int argc, char *argv[]) { test ("hello"); test ("1.2.3"); test ("1.a.2.3"); test ("1a.2.3.4"); test ("11.22.33.444"); printf ("All other are valid\n"); test ("1.2.3.4"); test ("11.22.33.44"); return 0; } #endif