/*
 * NOTE: This program depends on reading the ACL file under OS/2,
 * where lines are terminated with CR LF (2 bytes). Thus, the file
 * is being read in binary mode.
 * Under unix-alike operating systems this will not work, as here
 * a line is terminated only LF and so with only one byte.
 */

/* ***** BEGIN LICENSE BLOCK *****
* Version: CDDL 1.0
*
* The contents of this file are subject to the COMMON DEVELOPMENT AND
* DISTRIBUTION LICENSE (CDDL) Version 1.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of
* the License at http://www.sun.com/cddl/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is
* "netlabs.org Open Source Archive Administrator/Client"
*
* The Original Distribution Package is named
* "netlabs.org Open Source Archive Administrator/Client"
* and maintained and distributed by the Initial Developer
* and/or netlabs.org only.
*
* In addition to the CDDL the following applies:
* If you modify the Original Code, you may distribute it only
* as a part of a distribution package where
*  - the name of the package, created directories or
*    OS2.INI entries do not contain any of the terms
*    - "netlabs.org Open Source Archive"
*    - "NOSA"
*    - "NOSAC"
*    - "NOSAADM"
*  - neither netlabs.org nor the Initial Developer is stated as
*    the vendor or originator of the resulting Distribution Package,
*    which contains the Modified Code.
*
* The Initial Developer of the Original Code is
* netlabs.org: Christian Langanke <cla@clanganke.de>.
* Portions created by the Initial Developer are Copyright (C) 1999-2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* ***** END LICENSE BLOCK ***** */

#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>

#include <io.h>
#include <fcntl.h>
#include <sys\stat.h>

#define INCL_DOS
#define INCL_ERRORS
#include <os2.h>

#include "nosa.h"
#include "cvsstr.h"
#include "cvsacl.h"
#include "cvsenv.h"

#define __PROGRAM__ "cvssec"

#define PARM_VERBOSE    "Verbose"
#define PARM_HELP       "?"
#define PARM_HELP2      "H"

#ifdef DEBUG
#define DPRINTF(p)  printf p
#else
#define DPRINTF(p)
#endif


// global variables
static   BOOL           fVerbose        = FALSE;
static   BOOL           fHelp           = FALSE;

// --------------------------------------------------------

static APIRET _writeLog( PSZ pszLogfile, PSZ pszMessageFormat, ...)

{
         va_list        arg_ptr;
         FILE          *hfileLog;


if ((pszLogfile) && (pszMessageFormat))
   {

   va_start(  arg_ptr, pszMessageFormat);

#ifdef DEBUG

   printf( "\n\nLog Output:\n");
   vprintf( pszMessageFormat, arg_ptr);

#else

   // write logfile, if it exists
   if (!_access( pszLogfile, 0))
      {
      hfileLog = fopen( pszLogfile, "a");
      if (hfileLog)
         {
         vfprintf( hfileLog, pszMessageFormat, arg_ptr);
         fclose( hfileLog);
         }
      }

#endif

   va_end(  arg_ptr);
   }

return NO_ERROR;
}

// --------------------------------------------------------

static APIRET _showHelp( VOID)
{
printf( "%s - " VERSIONLIT " - "SHORTNAME " " ADMIN_PROGTYPE "\n"
        "Copyright (c) " AUTHOR " for " VENDOR ", " YEARS "\n"
        "\n"
        "   This is a filter program for CVS implementing additional security\n"
        "   for CVS archives under OS/2. It is only to be called by CVS.EXE.\n"
        , __PROGRAM__);

return ERROR_INVALID_PARAMETER;
}


// --------------------------------------------------------

INT main( ULONG argc, PSZ argv[])

{
         APIRET         rc = NO_ERROR;
         PCVSENV        pcvsenv = NULL;
         ULONG          i;

         PSZ            pszCommand     = NULL;
         PSZ            pszAccessPath  = NULL;
         PSZ            pszAccessFile  = NULL;

         PSZ            pszRootAcl;
         PSZ           *apszAclList;
         ULONG          ulAclCount;

         PSZ           *apszAcl;
         PSZ            pszTagName;
         PSZ            pszOperation;
         BOOL           fAllowed;
         CHAR           szAction[ 128];

do
   {
   printf( "\n");

   // check parms
   if (argc < 4)
      {
      rc = _showHelp();
      break;
      }

   // get environment being set by CVS.EXE
   pcvsenv = GetEnvironment();
   if (!pcvsenv)
      {
      rc = ERROR_ENVVAR_NOT_FOUND;
      break;
      }

   // read ACL list
   rc = ReadAclFile( pcvsenv->szWriteInfoFile,
                     &ulAclCount, &apszAclList);
   if (rc != NO_ERROR)
      break;

#ifdef DUMPACL
   printf( "\n%u ACLs read:\n", ulAclCount);
   for (i = 0, apszAcl = apszAclList; i < ulAclCount; i++, apszAcl++)
      {
      printf( "%s\n", *apszAcl);
      }
#endif

   // check for command
   pszCommand  = argv[ 1];


   /**/ if (!stricmp( pszCommand, "checkcommit"))
      {
      if (argc < 4)
         {
         rc = _showHelp();
         break;
         }
      pszAccessPath  = argv[ 2];
      pszAccessFile  = argv[ 3];
      dosslash( pszAccessPath);
      strcpy( szAction, "commit");
      fAllowed = IsCommitAllowed( pcvsenv, apszAclList, ulAclCount, pszAccessPath);
      }

   else if (!stricmp( pszCommand, "checktag"))
      {
      if (argc < 5)
         {
         rc = _showHelp();
         break;
         }
      pszTagName     = argv[ 2];
      pszOperation   = argv[ 3];
      pszAccessPath  = argv[ 4];
      dosslash( pszAccessPath);
      sprintf( szAction, "tag (%s \"%s\")", pszOperation, pszTagName);
      fAllowed = IsTagAllowed( pcvsenv, apszAclList, ulAclCount, pszTagName, pszAccessPath);
      }

   // write logfile
   rc = _writeLog( pcvsenv->szWriteInfoLog,
                   "%c: %s in %s %s for user %s\n",
                   (fAllowed) ? '0' : '#',
                   szAction,
                   pszAccessPath,
                   (fAllowed) ? "allowed" : "denied",
                   pcvsenv->pszUser);

   } while (FALSE);

// return 0 or 1
if (!rc)
   {
   if (fAllowed)
      rc = NO_ERROR;
   else
      rc = ERROR_INVALID_FUNCTION;
   }

DPRINTF(( "# rc=%u\n", rc));
return rc;

}

