/******************************************************************************
 * FIDOCONFIG --- library for fidonet configs
 ******************************************************************************
 * fidoconfig to binkd config converter:
 *     generate passwords file or
 *     simple binkd config file (may include it into real config)
 *
 * Copyright (C) 2002
 * Stas Degteff
 * Fido:     2:5080/102
 * Internet: g@grumbler.org
 * Copyrigth (c) Husky Developers Team
 * http://husky.sourceforge.net
 *
 * This file is part of FIDOCONFIG.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; see file COPYING. If not, write to the Free
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * See also http://www.gnu.org
 *****************************************************************************/

#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <smapi/compiler.h>

#ifdef HAS_IO_H
#  include <io.h>
#endif
#ifdef HAS_UNISTD_H
#  include <unistd.h>
#endif

#include "fidoconf.h"
#include "common.h"

#ifndef VERSION_H
#define VERSION_H

#include "version.h"
#include "cvsdate.h"

#endif

/* ANSI C knows nothing about this constant */
#ifndef F_OK
#define F_OK 0
#endif

char *program_name=NULL;

#define BINKDLOG "binkd.log"

int force_flag = 0; /* Force rewriting flag */

void printversion(FILE *fd){
  char *versionStr = NULL;

  versionStr = GenVersionStr( "fconf2binkd", FC_VER_MAJOR,
	                 FC_VER_MINOR, FC_VER_PATCH, FC_VER_BRANCH, cvs_date);

  printf("%s\n\n", versionStr);
}

void usage(int retcode){
      printf("Usage: fconf2binkd [-c fidoconfig] [options] [output_file_name]\n");
      printf("Options:  -h\t- print usage information\n");
      printf("\t  -c\t- specify alternate fidoconfig\n");
      printf("\t  -f\t- force owerwrite file\n");
      printf("\t  -p\t- generate passwords file\n");
      exit(retcode);
}

FILE *createOutputFile(const char *ofname){
  FILE *ofd;

  if( ofname ){
    if( !(access(ofname,F_OK) || force_flag) ){
      fprintf( stderr, "File '%s' exist!", ofname );
      return NULL;
    }
    if( !(ofd=fopen(ofname, "w+t")) ){
      fprintf( stderr, "Can't open file '%s': %s!", ofname, strerror(errno) );
      return NULL;
    }
  }else ofd=stdout;
  return ofd;
}

 /* doublicate backslash in output */
int printPath(char *path, FILE *ofd){
  int rc=1;

  for( ; rc && *path; path++ ){
      if( *path=='\\' ) rc = (EOF != fprintf( ofd, "\\\\"));
      else rc = fputc(*path, ofd);
  }
  return !rc;
}

/* Write passwords file:
 * ;comment
 * <address> <password>
 * <address>
 */
int writePasswords( s_fidoconfig *config, char * ofname ){
  FILE *ofd=NULL;
  unsigned ll = config->linkCount;

  ofd = createOutputFile(ofname);

  if( !ofd ) /* can't create */
    return 2;

  fprintf( ofd, "; binkd / t-mail passwords file\n; generated by ");
  printversion( ofd );
  fprintf( ofd, "\n\n" );

  for( ; ll-- ; ){
    fprintf( ofd, "%s %s\n",
            aka2str(config->links[ll].hisAka), 
            config->links[ll].sessionPwd ? config->links[ll].sessionPwd
                                         : (config->links[ll].defaultPwd ?
                                            config->links[ll].defaultPwd : "" )
           );
  }

  return 0;
}

/* Write max. possible binkd config
 *
 */
int writeBinkdConfig( s_fidoconfig *config, const char *ofname ){
  FILE *ofd=NULL;
  int rc=0;
  unsigned ll;

  ofd = createOutputFile(ofname);

  if( !ofd ) /* can't create */
    return 2;

  fprintf( ofd, "# binkd config file\n# generated by ");
  printversion(ofd);

  /* Address, paths & etc. */
    fprintf( ofd, "\n# The name of your system, it's location, and your name\n");
    if( config->name )
       fprintf( ofd, "sysname   \"%s\"\n", config->name );
    if( config->location )
      fprintf( ofd, "location  \"%s\"\n", config->location );
    if( config->sysop )
      fprintf( ofd, "sysop     \"%s\"\n\n", config->sysop );

    fprintf( ofd, "# Your addresses, 4D or 5D:\naddress" );
    for( ll=config->addrCount ; ll-- ; ){
      fprintf( ofd, " %s", aka2str(config->addr[ll]) );
    }

    fprintf( ofd, "\n\n# Your FTN domains:\ndomain fidonet " );
    printPath( config->outbound, ofd );
    fprintf( ofd, " %u\n\n", config->addr->zone);

    fprintf( ofd, "# Path and name for the logfile\nlog " );
    printPath( config->logFileDir, ofd );
    fprintf( ofd, BINKDLOG "\n" );
    if( config->protInbound ){
      fprintf( ofd, "\n# Inbound directory for secure links\ninbound " );
      printPath( config->protInbound, ofd );
    }
    if( config->inbound ){
      fprintf( ofd, "\n\n# Inbound directory for non-secure links\ninbound-nonsecure " );
      printPath( config->inbound, ofd );
    }
    if( config->minDiskFreeSpace )
      fprintf( ofd, "\n\n# Free space limit for receive next file\nminfree %u\n", config->minDiskFreeSpace );
    else fputc( '\n', ofd );

  /* Links:
   Set out-box flavor to "crash"
   */

  fprintf( ofd, "\n# Define a link:\n"
          "# node [[z:]n/]n[.p][@domain] [-nr] [{hosts|-} [{pwd|-} [flavour [{obox|-} [{ibox|-}]]]]]\n"
         );
  for( ll=config->linkCount ; ll-- ; ){
    fprintf( ofd, "Node %s * %s %c %s\n",
            aka2str(config->links[ll].hisAka), 
            config->links[ll].sessionPwd ? config->links[ll].sessionPwd
                                         : (config->links[ll].defaultPwd ?
                                            config->links[ll].defaultPwd : "" ),
             config->links[ll].fileBox ? 'c' : ' ',
             config->links[ll].fileBox ? config->links[ll].fileBox : ""
           );
  }

  return rc;
}

int main (int argc, char *argv[]) {
   s_fidoconfig *config=NULL;
   char *ofname=NULL;  /* output file name */
   char *fcfname=NULL; /* fidoconfig file name */
   char *p=NULL;
   int i=1, rc=0;
   unsigned passwords_list_only=0;

   /* Constucte program name from calling string */
   p=strrchr(argv[0],PATH_DELIM);
   if( p ) program_name = p+1;
   else program_name = "fconf2binkd";

   printversion(stdout);

   for( ; i<argc; i++ ){
     if( argv[i][0] != '-' ){ /* parameter: output filename */
       ofname = sstrdup( argv[i] );
       break;
     }
     switch( argv[i][1] ){
     case 'h':
     case 'H': /* help request */
               usage(1);
     case 'f': /* Force rewriting file */
               force_flag = 1;
               break;
     case 'c': /* fidoconfig file name */
               if( ++i<argc ) fcfname = sstrdup( argv[i] );
               else{
                 fprintf(stderr, "'%s' option require parameter!\n", argv[i-1]);
                 usage(-1);
               }
               break;
     case 'p': /* generate passwords list */
               passwords_list_only=1;
               break;
     default:  /* unknown option */
               fprintf(stderr,"Illegal parameter: %s\n",argv[i]);
               usage(1);
     }
   }

   config = readConfig(fcfname);
   if ( config ) {
     if( ofname ) /* if not defined output binkd config to stdout */
       printf("Generate binkd %s file %s\n", passwords_list_only ? "passwords" : "config" , ofname);

     if( passwords_list_only )
       rc = writePasswords( config, ofname );
     else
       rc = writeBinkdConfig( config, ofname );

     disposeConfig( config );
     return rc;
   }

   return 1;
}
