/* Copyright (C) 1993,1994 by the author(s).
 
 This software is published in the hope that it will be useful, but
 WITHOUT ANY WARRANTY for any part of this software to work correctly
 or as described in the manuals. See the ShapeTools Public License
 for details.

 Permission is granted to use, copy, modify, or distribute any part of
 this software but only under the conditions described in the ShapeTools 
 Public License. A copy of this license is supposed to have been given
 to you along with ShapeTools in a file named LICENSE. Among other
 things, this copyright notice and the Public License must be
 preserved on all copies.
*/
/*
 * AtFStk -- Attribute Filesystem Toolkit Library
 *
 * vbind.c -- Version Binding main program
 *
 * Author: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
 *
 * $Header: vbind.c[7.0] Thu Mar 10 12:21:47 1994 andy@cs.tu-berlin.de frozen $
 */

#include "atfs.h"
#include "sttk.h"
#include "atfstk.h"
#include "bind.h"

extern BindBaseline bindExact;

LOCAL int  dumpRules = FALSE;
LOCAL int  listRules = FALSE;
LOCAL int  testRules = FALSE;

LOCAL int handleAlias (option, arg)
     char *option, *arg;
{
  if (!arg || !(*arg)) {
    sprintf (stMessage, "No version alias name -- '%s' ignored.", option);
    stLog (stMessage, ST_LOG_ERROR);
    return (1);
  }

  bindExact.baselineString = arg;
  bindExact.baselineType = AT_BIND_ALIAS;
  return (0);
}

LOCAL int handleDate (option, arg)
     char *option, *arg;
{
  if (!arg || !(*arg)) {
    sprintf (stMessage, "No date specified -- '%s' ignored.", option);
    stLog (stMessage, ST_LOG_ERROR);
    return (1);
  }

  if ((bindExact.baselineDate = stMktime (arg)) == 0) {
    sprintf (stMessage, "Invalid date specified -- '%s' ignored.", option);
    stLog (stMessage, ST_LOG_ERROR);
    return (1);
  }
  bindExact.baselineType = AT_BIND_DATE;
  return (0);
}

LOCAL int handleVersions (option, arg)
     char *option, *arg;
{
  char *genPtr, *revPtr;

  if (!arg || !(*arg)) {
    sprintf (stMessage, "No version number specified -- '%s' ignored.", option);
    stLog (stMessage, ST_LOG_ERROR);
    return (1);
  }
  bindExact.baselineType = AT_BIND_VNUM;

  if (!strcmp (arg, "busy")) {
    bindExact.baselineGen = AF_BUSYVERS;
    bindExact.baselineRev = AF_BUSYVERS;
    return 0;
  }
  genPtr = arg;
  if ((revPtr = strchr (arg, '.'))) {
    *revPtr = '\0';
    revPtr++;
  }
  bindExact.baselineGen =  bindExact.baselineRev = AF_NOVNUM;
  if (genPtr && *genPtr) 
    bindExact.baselineGen = atoi (genPtr);
  if (revPtr && *revPtr)
    bindExact.baselineRev = atoi (revPtr);
  return 0;
}

LOCAL int printVersion ()
{
  sprintf (stMessage, "This is %s version %s", stProgramName, atVersion());
  stLog (stMessage, ST_LOG_MSG);
  sprintf (stMessage, "   using AtFS version %s", af_version());
  stLog (stMessage, ST_LOG_MSG);
  sprintf (stMessage, "     and Sttk version %s.", stVersion());
  stLog (stMessage, ST_LOG_MSG);
  stExit (0);
  return (0);
}

static int usage();

static StOptDesc optDesc[] = {
  { "?",	PCALL,		usage,		  NULL,			NULL },
  { "alias",	PCALL|PARG,	handleAlias,	  NULL,			NULL },
  { "date",	PCALL|PARG,	handleDate,	  NULL,			NULL },
  { "help",	PCALL,		usage,		  NULL,			NULL },
  { "nomsg",	PSWITCH|PSET,	NULL,		  &atBindNoMsg,		NULL },
  { "ruledump",	PSWITCH|PSET,	NULL,		  &dumpRules,		NULL },
  { "ruleerr",	PSWITCH|PSET,	NULL,		  &atBindDisplayErrors,	NULL },
  { "rulelist",	PSWITCH|PSET,	NULL,	 	  &listRules,		NULL },
  { "ruletest",	PSWITCH|PSET,	NULL,	  	  &testRules,		NULL },
  { "version",	PCALL,		printVersion,	  NULL,			NULL },
  { "vnum",	PCALL|PARG,	handleVersions,	  NULL,			NULL },
  { NULL, 	0, 		NULL,		  NULL, 		NULL },
};

LOCAL int usage()
{
  stLog ("Usage:", ST_LOG_MSGERR);
  stShortUsage (stProgramName, optDesc, "names...");
  atBindUsage ("");
  stExit (1);
  return (1);
}

/*==================
 *  main
 *==================*/

int main (argc, argv)
     int argc;
     char **argv;
{
  int  tmpArgc, newArgc, i, j, retCode = 0;
  char *cp, **tmpArgv, **newArgv;
  Af_set *resultSet;
  Af_key tmpKey;

  stProgramName = (cp = strrchr (argv[0], '/')) ? ++cp : argv[0];

  if (stParseArgs (argc, argv, &tmpArgc, &tmpArgv, optDesc))
    stExit (1);

  if (atBindOptions (tmpArgc, tmpArgv, &newArgc, &newArgv))
    stExit (1);

  if (listRules) {
    char **ruleList;
    if ((ruleList = atBindListRules ()) == NULL) {
      stLog (atBindErrorMsg, ST_LOG_ERROR);
      return (1);
    }

    i=0;
    while (ruleList[i]) {
      sprintf (stMessage, "%s", ruleList[i++]);
      stLog (stMessage, ST_LOG_MSG);
    }
    free (ruleList);
  }
 
  if (testRules) {
    for (i = 1; i < newArgc; i++) {
      if (atBindTestRule (newArgv[i])) {
	sprintf (stMessage, "%s -- ok.", newArgv[i]);
      }
      else {
	sprintf (stMessage, "%s -- not found.", newArgv[i]);
	retCode++;
      }
      stLog (stMessage, ST_LOG_MSG);
    }
  return (retCode);
  }

  for (i = 1; i < newArgc; i++) {
    if ((resultSet = atBindSet (newArgv[i], NULL, 0)) == NULL) {
      if (atBindError) {
	sprintf (stMessage, "(%s) %s", newArgv[i], atBindErrorMsg);
	stLog (stMessage, ST_LOG_ERROR);
      }
      retCode = 255;
      continue;
    }
    for (j=0; j<af_nrofkeys (resultSet); j++) {
      af_setgkey (resultSet, j, &tmpKey);
      sprintf (stMessage, "%s", af_retattr (&tmpKey, AF_ATTBOUND));
      stLog (stMessage, ST_LOG_MSG);
      af_dropkey (&tmpKey);
    }
    if (af_nrofkeys (resultSet) == 0)
      retCode++;
    af_dropset (resultSet);
  }

  if (dumpRules)
    atBindShowRules ();

  return (retCode);
}

