/***************************************************************************/
/*                                                                         */
/*    PROGRAM NAME: ACCSINFO                                               */
/*    -------------                                                        */
/*    OS/2 Lan Server 3.0  API sample program.                             */
/*    @Copyright International Business Machines Corp. 1984, 1992          */
/*    @Copyright Microsoft Corp. 1984, 1991                                */
/*                                                                         */
/*    What this program does:                                              */
/*                It gets the OS/2 LAN Server Access Control information   */
/*                for a given resource. The user may change                */
/*                any or all of that information.                          */
/*                                                                         */
/*                This program can operate both locally and                */
/*                remotely. The machine running this program must          */
/*                be logged onto the LAN with Administrator                */
/*                authority.                                               */
/*                                                                         */
/*    REQUIRED FILES:                                                      */
/*    ---------------                                                      */
/*    ACCSINFO.MAK    - IBM C-set/2 NMAKE file                             */
/*    ACCSINFO.C      - C source code for the main program.                */
/*    ERRMSG.C        - C source code for the Error_Message function.      */
/*                                                                         */
/*    REQUIRED LIBRARIES:                                                  */
/*    -------------------                                                  */
/*    NETAPI.LIB     -  Netapi library for OS/2                            */
/*                       (in the APITK\OS2\LIB directory).                 */
/*                                                                         */
/*    NetAPI functions used in this program :                              */
/*    ---------------------------------------                              */
/*    NetAccessGetInfo                                                     */
/*    NetAccessSetInfo                                                     */
/*                                                                         */
/***************************************************************************/

/*------------------ OS/2 Include definitions -----------------------------*/
#define  INCL_BASE
#include <os2.h>

/*--------------LAN Systems API ToolKit Include definitions ---------------*/
#define  INCL_32                        /* use 32bit includes */
#include <lanserv\netcons.h>
#include <lanserv\access.h>
#include <lanserv\neterr.h>
#include <lanserv\audit.h>

/*--------------------- C Include definitions ------------------------------*/
#define  __TILE__                       /* include 16bit tiled memory calls */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/*-------------------------- Definitions -----------------------------------*/

#define NUMBER_OF_ACCESS_LEVELS   7
#define LENGTH_OF_ACCESS_LETTERS 16

/*--------------------- Function Declarations ------------------------------*/

VOID Error_Message( USHORT, PSZ);
VOID Alter_Attrib(        struct access_info_1 LSFAR *accinfo1Buf);
VOID Alter_Usergroup_ACP( struct access_list LSFAR   *acclistBuf);


/****************************************************************************/
/* Main C Function                                                          */
/*--------------------------------------------------------------------------*/

VOID main(argc, argv)
SHORT argc;
PCHAR argv[];
{
/*  SEL                selBuf              ; */
  CHAR               chAccess_string[LENGTH_OF_ACCESS_LETTERS+1];
  CHAR               chAlter[NUMBER_OF_ACCESS_LEVELS+1];
  PCHAR              pchResource         ;   /* Resource name               */
  PCHAR              pchServername = NULL;   /* Server name                 */
  SHORT              sCompare            ;
  SHORT              sLevel           = 0;   /* Level of share info         */
  SHORT              sParmnum         =-1;
  USHORT             usBuflen         = 0;   /* Size of buffer area         */
  USHORT             usCounter        = 0;
  USHORT             usRc             = 0;   /* API return code storage     */
  USHORT             usStep           = NUMBER_OF_ACCESS_LEVELS;
  USHORT             usTotalavail     = 0;   /* Total info available        */
  struct access_info_1  LSFAR  *accinfo1Buf;   /* Resource information buffer */
  struct access_list    LSFAR  *acclistBuf ;   /* Resource info. for a user   */
                                             /* or group.                   */

  /* Verify the validity of the input arguments.                            */

  switch ( argc ) {

  case 2 :                                         /* Assume that the       */
     if ( *(argv[1]+1) == ':' || *argv[1] == '\\') /* argument is the       */
        pchResource = argv[1];                     /* resource name.        */
     else {
        usRc = 1;
        printf(" Invalid Resourcename format.\n");
     } /* endif */
     break;

  case 3 :                                         /* Assume arguments are  */
     if ( *argv[1] == '\\' || * argv[1] == 'N')    /* server name and       */
        pchServername = argv[1];                   /* resource name.        */
     else {
           usRc = 1;
           printf("Invalid Servername format. \n");
     } /* endif */
     if ( *(argv[2]+1) == ':' || *argv[2] == '\\')
        pchResource = argv[2];
     else {
        usRc = 1;
        printf(" Invalid Resourcename format.\n");
     } /* endif */
     break;

  default :
           usRc = 1;
           printf(" Incorrect number of arguments.\n");

     break;
  } /* endswitch */

  /* If the input parameters are invalid, give instructions and exit.       */

  if ( usRc != 0) {
     printf(" \n");
     printf(" For remote execution, the correct format is :\n");
     printf("        %s <servername> <Resourcename> \n\n",argv[0]);
     printf(" For local execution, the correct format is  :\n");
     printf("        %s <Resourcename>\n\n",argv[0]);

     printf(" Servername   : \\\\<server machinename>\n");
     printf(" Resourcename : <drive>:\\<pathname> \n");
     printf("           OR   \\pipe\\<pipename> \n");
     printf("           OR   \\print\\<queuename> \n");
     printf("           OR   \\comm\\<chardevqueue> \n");

     DosExit(EXIT_PROCESS, usRc);
  } /* endif */

  sLevel = 1; /* The only access permission data structure level that is    */
              /* valid for both GetInfo and SetInfo is level 1.             */

  usRc = NetAccessGetInfo( pchServername,         /* Initial call to        */
                           pchResource,           /* establish how big a    */
                           sLevel,                /* buffer is required.    */
                           NULL,
                           usBuflen,
                          &usTotalavail);

  /* Allocate space for the access_info_1 buffer plus the access control
     buffers. */

  usBuflen = usTotalavail;
/* comment out old 16bit call
  DosAllocSeg(usBuflen, &selBuf, SEG_NONSHARED);
  accinfo1Buf = (struct access_info_1 LSFAR *) MAKEP(selBuf, 0);
*/
  accinfo1Buf = (struct access_info_1 *)_tmalloc( usBuflen);

  usRc = NetAccessGetInfo( pchServername,         /* Call to get information*/
                           pchResource,
                           sLevel,
               (PCHAR LSFAR) accinfo1Buf,
                           usBuflen,
                          &usTotalavail);

  Error_Message(usRc,"NetAccessGetInfo");/* If necessary, send an error msg */

  /* Print out the resource audit information                               */

  printf("Servername                                   : %s\n",
                                                 pchServername);
  printf("Level                                        : %d\n",sLevel);
  printf("Resource name                                : %s\n",
                               accinfo1Buf->acc1_resource_name);

  printf("                   Universal Access Control Attributes\n");
  printf("                -----------------Audit Events------------\n");
  printf("    |           Successful            |");
  printf("            Failed\n");
  printf("All | Open Write/Create Delete Access |");
  printf(" Open Write/Create Delete Access |\n");
  printf(" %01d      %01d       %01d         %01d      %01d  ",
         (accinfo1Buf->acc1_attr & AA_AUDIT_ALL),
         ((accinfo1Buf->acc1_attr & AA_S_OPEN)>> 4),
         ((accinfo1Buf->acc1_attr & AA_S_WRITE)>> 5),
         ((accinfo1Buf->acc1_attr & AA_S_DELETE)>> 6),
         ((accinfo1Buf->acc1_attr & AA_S_ACL)>> 7));
  printf("      %01d       %01d         %01d       %01d\n ",
         ((accinfo1Buf->acc1_attr & AA_F_OPEN)>> 8),
         ((accinfo1Buf->acc1_attr & AA_F_WRITE)>> 9),
         ((accinfo1Buf->acc1_attr & AA_F_DELETE)>> 10),
         ((accinfo1Buf->acc1_attr & AA_F_ACL)>> 11));

/* Check whether or not the user wishes to change any of the auditing       */
/* parameters.                                                              */

  printf("Alter Attributes (Yes/No)  ");
  scanf("%s",chAlter);

  if (*chAlter == 'Y' || *chAlter == 'y') {
     Alter_Attrib(accinfo1Buf);
     sParmnum = ACCESS_ATTR_PARMNUM;
  }

  printf("Number of User/Group Access Control Profiles : %d\n"
                                      ,accinfo1Buf->acc1_count);

  if ( accinfo1Buf->acc1_count > 0) {
     accinfo1Buf += 1;                                    /* Set the pointer*/
     acclistBuf = (struct access_list LSFAR *) accinfo1Buf; /* for the group/ */
     accinfo1Buf -= 1;                                    /* user profiles. */

     /*  Print out the information for each user/group profile.             */
     do {
        printf("/--------------------\\\n");
        printf("|  User/Group name   : %s\n",acclistBuf->acl_ugname);

        strcpy(chAccess_string, ACCESS_LETTERS); /* Reset the loop variables*/
        sCompare = ACCESS_PERM;
        usStep   = NUMBER_OF_ACCESS_LEVELS;

        /* If the access profile is not set up for ALL access, then check   */
        /* each access bit (Read, Write, ...), and replace the output       */
        /* character with a blank if the bit is not set.                    */

        if ((acclistBuf->acl_access & ACCESS_ALL) != ACCESS_ALL)
           do {
              if ((sCompare & acclistBuf->acl_access) == 0)
                 chAccess_string[usStep-1] = ' ';

              sCompare = sCompare >> 1;

           } while ( --usStep > 0); /* enddo */

        printf("|  Access Permission : %s\n",chAccess_string);
        printf("\\--------------------/\n\n");

        printf("Change %s ACP (Yes/No) ?",acclistBuf->acl_ugname);
        scanf("%s",chAlter);

        if ( *chAlter == 'Y' || *chAlter == 'y') {
           Alter_Usergroup_ACP( acclistBuf);
           sParmnum = 0;
        }

                   acclistBuf++;

     } while ( ++usCounter < (USHORT) accinfo1Buf->acc1_count); /* enddo */
  } /* endif */

  switch ( sParmnum) {
  case 0 :                                             /* If any user/group */
     usRc = NetAccessSetInfo( pchServername,           /* profiles have been*/
                              pchResource,             /* changed, send the */
                              sLevel,                  /* access_info_1 data*/
                  (PCHAR LSFAR) accinfo1Buf,             /* structure, plus   */
                              usBuflen,                /* all access_list   */
                              sParmnum);               /* data structures   */
     break;
  case ACCESS_ATTR_PARMNUM :

     usBuflen = sizeof(accinfo1Buf->acc1_attr);        /* If only the       */
                                                       /* acc1_attr field of*/
     usRc = NetAccessSetInfo( pchServername,           /* the access_info_1 */
                              pchResource,             /* data structure has*/
                              sLevel,                  /* been changed,     */
                  (PCHAR LSFAR) &(accinfo1Buf->acc1_attr), /* send it alone.  */
                              usBuflen,
                              sParmnum);
     break;
  } /* endswitch */

  Error_Message(usRc,"NetAccessSetInfo");/* If necessary, send an error msg */
  _tfree( accinfo1Buf);

} /* end main */


/****************************************************************************/
/* Alter_Attrib                                                             */
/*      Alter the Auditing attributes for a given resource.                 */
/*--------------------------------------------------------------------------*/

VOID Alter_Attrib( struct access_info_1 LSFAR *accinfo1Buf)

{
  CHAR chAlter[NUMBER_OF_ACCESS_LEVELS+1];

  printf("Audit All (Yes/No) ?");
  scanf("%s",chAlter);

  switch (*chAlter) {
  case 'Y':
  case 'y':
     accinfo1Buf->acc1_attr = AA_AUDIT_ALL;
     break;
  case 'N':                      /* Clear the AUDIT_ALL field               */
  case 'n':
     accinfo1Buf->acc1_attr = accinfo1Buf->acc1_attr & ~AA_AUDIT_ALL;
     break;
  } /* endswitch */

  /* It is not valid to set other records in the audit field if the         */
  /* AUDIT_ALL record is set.                                               */

  if ( (accinfo1Buf->acc1_attr & AA_AUDIT_ALL) != AA_AUDIT_ALL) {

    printf("Audit all successful actions (Y/N) ?");
    scanf("%s", chAlter);

    switch (*chAlter) {
    case 'Y':
    case 'y':
       accinfo1Buf->acc1_attr = accinfo1Buf->acc1_attr | AA_S_ALL;
       break;
    case 'N':
    case 'n':
       accinfo1Buf->acc1_attr = accinfo1Buf->acc1_attr & ~AA_S_ALL;
       break;
    } /* endswitch */

    printf("Audit all failed actions (Y/N) ?");
    scanf("%s", chAlter);

    switch (*chAlter) {
    case 'Y':
    case 'y':
       accinfo1Buf->acc1_attr = accinfo1Buf->acc1_attr | AA_F_ALL;
       break;
    case 'N':
    case 'n':
       accinfo1Buf->acc1_attr = accinfo1Buf->acc1_attr & ~AA_F_ALL;
       break;
    } /* endswitch */
  } /* endif */

} /* end Alter_Attrib */


/****************************************************************************/
/* Alter_Usergroup_ACP Function                                             */
/*      Make changes to the Access Control Profile of                       */
/*      an individual user or group of users.                               */
/*--------------------------------------------------------------------------*/

VOID Alter_Usergroup_ACP( struct access_list LSFAR *acclistBuf)

{
  CHAR     chAlter[NUMBER_OF_ACCESS_LEVELS+1];
  SHORT    sParmnum = 0;
  USHORT   usStep   = 0;

  printf("All Privileges (Y/N) ?");
  scanf("%s",chAlter);

  switch (*chAlter) {
  case 'Y':
  case 'y':
     acclistBuf->acl_access = ACCESS_ALL;
     break;
  case 'N':
  case 'n':
     acclistBuf->acl_access = acclistBuf->acl_access  /* Clear all access   */
                            & ~ACCESS_ALL;            /* field bits.        */
     printf("Desired Privileges (RWCXDAP) :");
     scanf("%s",chAlter);

     /* Set the access field bits where the user has specified that they be */
     /* set.                                                                */
     do {

        switch (*(chAlter+usStep)) {
        case 'R':
        case 'r':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_READ;
           break;
        case 'W':
        case 'w':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_WRITE;
           break;
        case 'X':
        case 'x':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_EXEC;
           break;
        case 'C':
        case 'c':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_CREATE;
           break;
        case 'D':
        case 'd':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_DELETE;
           break;
        case 'A':
        case 'a':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_ATRIB;
           break;
        case 'P':
        case 'p':
           acclistBuf->acl_access = acclistBuf->acl_access
                            | ACCESS_PERM;
           break;
        } /* endswitch */
        usStep++;

     } while ( *(chAlter+usStep) ); /* enddo */
     break;

  } /* endswitch */

} /* end Alter_Usergroup_ACP */

