/*
 *   NVRAM WakeUp
 *   Copyright (C) 2001-2004, Sergei Haller.
 *
 *   $Id: tools.c 912 2009-05-17 17:19:06Z tiber $
 *
 *   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; either version 2 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#define CVSREV_tools_c \
     "$Id: tools.c 912 2009-05-17 17:19:06Z tiber $"

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <syslog.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>

#include "nvram-wakeup.h"

static char *progname         = NULL;
static int  _to_syslog        = OFF;
static int  _print_debug_msgs = OFF;

const char * get_progname(void){
     return progname;
}

void set_progname(const char * str){
     char * prg = NULL;
     
     prg = strrchr(str, '/');
     prg = (prg ? (prg + 1) : (char *)str);
     progname = strdup(prg);
}

void  enable_syslog(void){ _to_syslog = ON;  }
void disable_syslog(void){ _to_syslog = OFF; }

void  enable_debug (void){ _print_debug_msgs = ON;  }
void disable_debug (void){ _print_debug_msgs = OFF; }

void nvprintf(int lvl, char *fmt, ...) {
     int n, size = 100; /* Guess we need no more than 100 bytes. */
     char *msg;
     FILE *out;
     va_list ap;

     switch (lvl) {
       case LOG_EMERG:   /* system is unusable                   */         
               out = stderr;
               break;
       case LOG_ALERT:   /* action must be taken immediately     */
               out = stderr;
               break;
       case LOG_CRIT:    /* critical conditions                  */
               out = stderr;
               break;
       case LOG_ERR:     /* error conditions                     */
               out = stderr;
               break;
       case LOG_WARNING: /* warning conditions                   */
               out = stderr;
               break;
       case LOG_NOTICE:  /* normal, but significant, condition   */
               out = stdout;
               break;
       case LOG_INFO:    /* informational message                */
               out = stdout;
               break;
       case LOG_DEBUG:   /* debug-level message                  */ 
       default:          /* unknown log level                    */
               lvl = LOG_DEBUG;
               out = stderr;
               if (! _print_debug_msgs)
                    return;   /* don't print debug messages      */
               break;
     }                      

     if (! _to_syslog) { /* to stderr/stdout */
          va_start(ap, fmt);
          if (lvl <= LOG_WARNING || lvl == LOG_DEBUG)
               /* begin the line with the program name
                * in DEBUG and in WARNING/ERR/CRIT/ALERT/EMERG mode
                */
               fprintf(out, "%s: ", progname);
          vfprintf(out, fmt, ap);
          va_end(ap);
          return;
     }
     else { /* via syslog */
          if ((msg = malloc (size)) == NULL) {
               /* output to stderr/stdout anyway. */
               syslog(LOG_ERR, "Couldn't allocate enough memory (%d Bytes) for syslog message %s.\n", size, strerror(errno));
               va_start(ap, fmt);
               fprintf(out, "%s: ", progname);
               vfprintf(out, fmt, ap);
               va_end(ap);
               return;
          }
          while (1) {                                              
               /* Try to print in the allocated space. */
               va_start(ap, fmt);
               n = vsnprintf(msg, size, fmt, ap);
               va_end(ap);

               /* If that worked, log the string and free the allocated space. */
               if (n > -1 && n < size) {
                    syslog(lvl, msg);
                    free(msg);
                    return;
               }

               /* Else try again with more space. */
               if (n > -1)      /* glibc 2.1 */
                    size = n+1; /* precisely what is needed */
               else             /* glibc 2.0 */
                    size *= 2;  /* twice the old size */

               if ((msg = realloc (msg, size)) == NULL) {
                    /* output to stderr/stdout anyway. */
                    syslog(LOG_ERR, "Couldn't allocate enough memory (%d Bytes) for syslog message %s.\n", size, strerror(errno));
                    va_start(ap, fmt);
                    fprintf(out, "%s: ", progname);
                    vfprintf(out, fmt, ap);
                    va_end(ap);
                    free(msg);
                    return;
               }
          }
     }
}

char * strip(char * s) {
     char *res;
     
     if (s==NULL) return s;
     
     /* strip whitespace */
     res = strdup(s);
     while(isspace(*res))
     /*   memmove(res, res+1, strlen(res)); */
          res++;
     while(isspace(res[strlen(res)-1]))
          res[strlen(res)-1]=0;
     return res;
}

void xxd(unsigned char * bytes, int size, int loglevel) {
     int i,pos;
     char out_line[50];
         
     for (i=0;i<=((size-1) / 16);i++) {
          sprintf(out_line, "%06X0: %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X %02X%02X\n", i,
                bytes[16*i+ 0], bytes[16*i+ 1], bytes[16*i+ 2], bytes[16*i+ 3],
                bytes[16*i+ 4], bytes[16*i+ 5], bytes[16*i+ 6], bytes[16*i+ 7],
                bytes[16*i+ 8], bytes[16*i+ 9], bytes[16*i+10], bytes[16*i+11],
                bytes[16*i+12], bytes[16*i+13], bytes[16*i+14], bytes[16*i+15] ); 
          if (size < (i+1)*16 ) {
              pos = ((size&0xF)>>1)*5 + (size&1)*3 + 8;
              assert(pos+1 < 50);
              out_line[pos]='\n';
              out_line[pos+1]=0;
          }
          nvprintf(loglevel, out_line);
     }
}

void cat(unsigned char * bytes, int size) {
     int i;
     for (i=0;i<size;i++)
          putchar(bytes[i]);
}



