
/*     Valerie Caro    COINS Research Computer Facility          */
/*     UNIVERSITY OF MASSACHUSETTS/ AMHERST, MA 01003            */

/*******************************************/
/* Show the disk quotas for an account on  */
/* all $1$DUA disks in the cluster.        */
/* Show total on all disks for one account */
/*******************************************/

#include descrip
#include dvidef
#include stdio
#include "gqm.h"

#define MAX_DISK_NUM 20 /* arbitrary maximum number for a disk on cluster */

#define GRP_HEADER "Account         Allocated           Used         Free\n"
#define BRF_HEADER "Disk            Allocated           Used         Free\n"
#define UNDERLINE  "------------------------------------------------------------------"

extern FILE *out_file;		 /* Output file */
extern struct idlist_type  *idlist;  /* Identifier list */

char    devname[64];
short 	ret_len=0;
int dtot_used , dtot_quota , dtot_free;
int dtot_used_user, dtot_free_user;

do_show_acc_disks(diskchan, groupnamed)
int *diskchan;
struct dsc$descriptor_s *groupnamed;
{
	int status, udiskchan, disk_num = 0;
	char disk_name[20];

	udiskchan = *diskchan;
	dtot_used = 0;
	dtot_quota = 0;
	dtot_free = 0;
	dtot_used_user = 0;
	dtot_free_user = 0;

/* OPEN EACH DISK AND LIST QUOTA */
/* Set Current Disk    */               
/* This is an easy way to get the disk names, though not very good */
/* In the future this should be changed. */

	for (;disk_num < MAX_DISK_NUM; ++disk_num)
	 { sprintf(disk_name, "$1$DUA%d", disk_num);
	   if (change_disk(disk_name, &udiskchan, strlen(disk_name)) == 1)
	       wrt_disk_report(udiskchan, groupnamed); 
	 }



/* Print calculated account totals  */
   fprintf(out_file,"\n       TOTAL\n       =====\n");
   wrt_header(GRP_HEADER);
   if (dtot_free < 0)
	 fprintf(out_file, "%8.8s       %10d     %10d   %10d Overdrawn\n",
			groupnamed->dsc$a_pointer, dtot_quota,dtot_used,
			 -dtot_free);
	else
	  fprintf(out_file, "%8.8s       %10d     %10d   %10d\n",
			groupnamed->dsc$a_pointer, dtot_quota,
			dtot_used, dtot_free);

   dtot_free_user = dtot_used - dtot_used_user;
   if (dtot_free_user < 0)
	  fprintf(out_file, "%8.8s       %10d     %10d   %10d Overdrawn\n\n",
		     	"USERS   ", dtot_used,dtot_used_user, -dtot_free_user);
	else
	  fprintf(out_file, "%8.8s       %10d     %10d   %10d \n\n",
	 	     	"USERS   ", dtot_used,dtot_used_user, dtot_free_user);
}  


do_show_brief_disks(diskchan, groupnamed)
int *diskchan;
struct dsc$descriptor_s *groupnamed;
{
	int status, udiskchan, disk_num = 0;
	char disk_name[20];

	udiskchan = *diskchan;
	dtot_used = 0;
	dtot_quota = 0;
	dtot_free = 0;

/* OPEN EACH DISK AND LIST QUOTA */
/* Set Current Disk    */               
/* This is an easy way to get the disk names, though not very good */
/* In the future this should be changed. */

   fprintf(out_file, "\n                  %8.8s\n", groupnamed->dsc$a_pointer);
   wrt_header(BRF_HEADER);

	for (;disk_num < MAX_DISK_NUM; ++disk_num)
	 { sprintf(disk_name, "$1$DUA%d", disk_num);
	   if (change_disk(disk_name, &udiskchan, strlen(disk_name)) == 1)
	       wrt_brief_disk_report(udiskchan, groupnamed); 
	 }



/* Print calculated account totals  */
   if (dtot_free < 0)
	 fprintf(out_file, "\n%-8.8s       %10d     %10d   %10d Overdrawn\n",
			"TOTAL", dtot_quota,dtot_used, -dtot_free);
	else
	  fprintf(out_file, "\n%-8.8s       %10d     %10d   %10d\n",
			"TOTAL", dtot_quota, dtot_used, dtot_free);

}  

do_show_tot_disks(diskchan, groupnamed)
int *diskchan;
struct dsc$descriptor_s *groupnamed;
{
	int status, udiskchan, disk_num = 0;
	char disk_name[20];

	udiskchan = *diskchan;
	dtot_used = 0;
	dtot_quota = 0;
	dtot_free = 0;

   fprintf(out_file,"\nTOTAL : ");

/* OPEN EACH DISK AND LIST QUOTA */
/* Set Current Disk    */               
/* This is an easy way to get the disk names, though not very good */
/* In the future this should be changed. */

	for (;disk_num < MAX_DISK_NUM; ++disk_num)
	 { sprintf(disk_name, "$1$DUA%d", disk_num);
	   if (change_disk(disk_name, &udiskchan, strlen(disk_name)) == 1)
		total_disk_quota(udiskchan, groupnamed);
	 }


/* Print calculated account totals  */
   fprintf(out_file, "\n");
   wrt_header(GRP_HEADER);
   if (dtot_free < 0)
	  fprintf(out_file, "%8.8s       %10d     %10d   %10d Overdrawn\n\n",
			groupnamed->dsc$a_pointer, dtot_quota,dtot_used,
			 -dtot_free);
	else
	  fprintf(out_file, "%8.8s       %10d     %10d   %10d\n\n",
			groupnamed->dsc$a_pointer, dtot_quota,
			dtot_used, dtot_free);
}

/* C+++++
C FUNCTION
C
C     change_disk sets the quota operations to a particular disk or volume.
C+++
C INPUT PARAMETERS
C
C     diskname	name of the disk
C+++
C OUTPUT PARAMETERS
C
C     chan	channel number for disk
C     status    returns status of operation
C+++++
*/
change_disk(diskname,quota_chan, length)
	char *diskname;
	int  *quota_chan, length;
	
      {
	int	status;			/*status return value*/
	struct  iosb_s { int io1, io2; } iosb;

	struct dvi_itm { short len, code;
			 char *buff_addr;
			 short  *retlen; 
			 int  end_of_buff; } dvi_item;

	$DESCRIPTOR(dnamed,diskname); 
	$DESCRIPTOR(devnamed, &devname);

	dnamed.dsc$w_length = length; 
	   
	dvi_item.len = 16;
	dvi_item.code = DVI$_DEVNAM;
	dvi_item.buff_addr = &devname;
	dvi_item.retlen = &ret_len;
	dvi_item.end_of_buff = 0;

	status = sys$getdviw(0, 0, &dnamed, &dvi_item, &iosb, 0,0,0);
	devnamed.dsc$w_length = ret_len;
	if (status != 1) return(status);

	if (*quota_chan != 0) 
	  { sys$dassgn(*quota_chan); 
	    status = grp_close();
	  }

	status=sys$assign(&devnamed, quota_chan,0,0);

	if (status == 1) 
	   status = grp_open(&devnamed);
	
/* 	IF ERROR IN DISK OR QUOTA FILE, SET CHANNEL TO 0 */
	if (status != 1)
	    *quota_chan = 0;
	devname[ret_len] = '\0';

	return(status);
      }

/*
C+++++
C     WRT_disk_REPORT outputs a report for the group whose name
C is specified on the command line.
C
C+++
C INPUT PARAMETERS
C
C     diskchan  channel of disk
C     group	name of the group for report
C+++
*/
wrt_disk_report(diskchan, groupd)
	unsigned diskchan;
	struct dsc$descriptor_s *groupd;
    {
	int status, grp_quota = 0, grp_used = 0, grp_free, quota,usage;
	int tot_quota = 0, tot_used = 0, tot_free = 0;
	unsigned uic;
	char acct[9],user[32];
	$DESCRIPTOR(userd,user);
	$DESCRIPTOR(acctd,acct);
	int length, free, first_user = 1, status1 = 0;
	struct idlist_type *id;


/* Find the groupname in the GROUP information file and return
   the data. */

	status = grp_get_info(groupd, &grp_quota, &grp_used);
	if ((status & 1) == 0) 
	       return;

	status = uaf_close();

    groupd->dsc$a_pointer[8] = '\0';
    length = strcspn(groupd->dsc$a_pointer,"0 ");

    while ((status = uaf_get_next_user(&userd, &uic, &acctd)) & 1)
     {
       if ((strncmp(acct,groupd->dsc$a_pointer,length) == 0) && 
		(strcspn(acct,"0 ") == length))
	{
/* Look up user in quota file and write report if present */
	status=utl_get_dquota(&diskchan,&uic,&quota,&usage);
        if (status == 980) /* quotas not active */
	   return;

/* WRITE HEADER IF FIRST USER AND QUOTAS ENABLED */
	if (first_user)
	{
	  first_user = 0;
	  fprintf(out_file,"\n       %*.*s\n       %*.*s\n",ret_len, ret_len, 
			devname, ret_len, ret_len, "================");
	  wrt_header(GRP_HEADER);

	  grp_free = grp_quota - grp_used;
	  if (grp_free < 0)
	    fprintf(out_file, "%8.8s       %10d     %10d   %10d Overdrawn\n\n",
			groupd->dsc$a_pointer, grp_quota,grp_used, -grp_free);
	  else
	    fprintf(out_file, "%8.8s       %10d     %10d   %10d\n\n",
			groupd->dsc$a_pointer, grp_quota,grp_used, grp_free);
	}


	if (status == 1) 
	 { free = quota-usage;
/*	   update account total */
	   tot_quota += quota;
	   tot_used  += usage;
	   tot_free  += free;

	   if (free < 0) 
	      fprintf(out_file, "%12.12s       %6d         %6d       %6d Overdrawn\n",
			user, quota,usage,-free);
	   else
	      fprintf(out_file, "%12.12s       %6d         %6d       %6d\n",user, quota,usage,free);
	  }
	}
      } /* while */

/*   Now list the identifiers also */
/*   First put all the identifiers in a linked list if haven't already */
     if (idlist == NULL) make_id_list();

     id = idlist;
     while (id != NULL)
       {
       	 if ((status1 = strncmp(id->idname, groupd->dsc$a_pointer,length)) == 0)
	   {
/* 	     Look up id in quota file and write report if present */
	     if (utl_get_dquota(&diskchan,&id->idval,&quota,&usage) == 1)
	      { free = quota-usage;
/*	   	update account total */
	   	tot_quota += quota;
	   	tot_used  += usage;
	   	tot_free  += free;

		if (free < 0) 
	      fprintf(out_file, "%12.12s*      %6d         %6d       %6d Overdrawn\n",
			id->idname, quota,usage,-free);
	        else
	      fprintf(out_file, "%12.12s*      %6d         %6d       %6d\n",
	     		id->idname, quota,usage,free);
	   } /* if get quota */
	  } /* if got id */

	   id = id->next;  /* go through list of ids */
	   if (status1 > 0) break; /* alphabetically ordered, so quit */
	 } /* while */


/* Print calculated account totals  */
   fprintf(out_file, "%54.54s\n", UNDERLINE);
   if (tot_free < 0)
      fprintf(out_file, "TOTAL          %10d     %10d   %10d Overdrawn\n\n\n",
			tot_quota, tot_used, -tot_free);
   else
       fprintf(out_file, "TOTAL          %10d     %10d   %10d\n\n\n",
			tot_quota, tot_used, tot_free);

/* SUM UP TOTALS FOR ALL DISKS */
   dtot_quota += grp_quota;
   dtot_used += grp_used;
   dtot_free += grp_free;
   dtot_used_user += tot_used;
  }

/*
C+++++
C     TOTAL_disk_QUOTA outputs the total quota for the group whose name
C is specified on the command line.
C
C+++
C INPUT PARAMETERS
C
C     diskchan  channel of disk
C     group	name of the group for report
C+++
*/
total_disk_quota(diskchan, groupd)
	unsigned diskchan;
	struct dsc$descriptor_s *groupd;
    {
	int status, grp_quota = 0, grp_used = 0, grp_free, quota,usage;
	int tot_quota = 0, tot_used = 0, tot_free = 0;
	unsigned uic;
	char acct[9],user[32];
	$DESCRIPTOR(userd,user);
	$DESCRIPTOR(acctd,acct);
	int length, free, first_user = 1, status1 = 0;
	struct idlist_type *id;


/* Find the groupname in the GROUP information file and return
   the data. */

	status = grp_get_info(groupd, &grp_quota, &grp_used);
	if ((status & 1) == 0) 
	       return;

	status = uaf_close();

    groupd->dsc$a_pointer[8] = '\0';
    length = strcspn(groupd->dsc$a_pointer,"0 ");

    while (((status = uaf_get_next_user(&userd, &uic, &acctd)) & 1) &&
		first_user)
     {
       if ((strncmp(acct,groupd->dsc$a_pointer,length) == 0) && 
		(strcspn(acct,"0 ") == length))
	{
/* Look up user in quota file and write report if present */
	status=utl_get_dquota(&diskchan,&uic,&quota,&usage);
        if (status == 980) /* quotas not active */
	   return;

	  grp_free = grp_quota - grp_used;
	  first_user = 0;
	}

      } /* while */

     if (first_user)
      {
/*   Now list the identifiers also */
/*   First put all the identifiers in a linked list if haven't already */
     if (idlist == NULL) make_id_list();

     id = idlist;
     while ((id != NULL) && (first_user))
       {
       	 if ((status1 = strncmp(id->idname, groupd->dsc$a_pointer,length)) == 0)
	   {
/* 	     Look up id in quota file and write report if present */
	     if (utl_get_dquota(&diskchan,&id->idval,&quota,&usage) == 1)
	      { 
		  grp_free = grp_quota - grp_used;
		  first_user = 0;

	      } /* if get quota */
	    } /* if got id */

	   id = id->next;  /* go through list of ids */
	   if (status1 > 0) break; /* alphabetically ordered, so quit */
	 } /* while */

  } /* if first_user */

/* SUM UP TOTALS FOR ALL DISKS */
  if (first_user == 0)
  {
   dtot_quota += grp_quota;
   dtot_used += grp_used;
   dtot_free += grp_free;
   fprintf(out_file," %*.*s ", ret_len, ret_len, devname);
  }
}



/*
C+++++
C     wrt_brief_disk_report outputs the total quota for the group whose name
C is specified on the command line.
C
C+++
C INPUT PARAMETERS
C
C     diskchan  channel of disk
C     group	name of the group for report
C+++
*/
wrt_brief_disk_report(diskchan, groupd)
	unsigned diskchan;
	struct dsc$descriptor_s *groupd;
    {
	int status, grp_quota = 0, grp_used = 0, grp_free, quota,usage;
	int tot_quota = 0, tot_used = 0, tot_free = 0;
	unsigned uic;
       	char acct[9],user[32];
	$DESCRIPTOR(userd,user);
	$DESCRIPTOR(acctd,acct);
	int length, free, first_user = 1, status1 = 0;
	struct idlist_type *id;


/* Find the groupname in the GROUP information file and return
   the data. */

	status = grp_get_info(groupd, &grp_quota, &grp_used);
	if ((status & 1) == 0) 
	       return;

	status = uaf_close();

    groupd->dsc$a_pointer[8] = '\0';
    length = strcspn(groupd->dsc$a_pointer,"0 ");

    while (((status = uaf_get_next_user(&userd, &uic, &acctd)) & 1) &&
		first_user)
     {
       if ((strncmp(acct,groupd->dsc$a_pointer,length) == 0) && 
		(strcspn(acct,"0 ") == length))
	{
/* Look up user in quota file and write report if present */
	status=utl_get_dquota(&diskchan,&uic,&quota,&usage);
        if (status == 980) /* quotas not active */
	   return;

	  grp_free = grp_quota - grp_used;
	  first_user = 0;
	}

      } /* while */

     if (first_user)
      {
/*   Now list the identifiers also */
/*   First put all the identifiers in a linked list if haven't already */
     if (idlist == NULL) make_id_list();

     id = idlist;
     while ((id != NULL) && (first_user))
       {
       	 if ((status1 = strncmp(id->idname, groupd->dsc$a_pointer,length)) == 0)
	   {
/* 	     Look up id in quota file and write report if present */
	     if (utl_get_dquota(&diskchan,&id->idval,&quota,&usage) == 1)
	      { 
		  grp_free = grp_quota - grp_used;
		  first_user = 0;

	      } /* if get quota */
	    } /* if got id */

	   id = id->next;  /* go through list of ids */
	   if (status1 > 0) break; /* alphabetically ordered, so quit */
	 } /* while */

  } /* if first_user */

/* SUM UP TOTALS FOR ALL DISKS */
  if (first_user == 0)
  {
   dtot_quota += grp_quota;
   dtot_used += grp_used;
   dtot_free += grp_free;
/* Print account totals  */
   if (grp_free < 0)
      fprintf(out_file, "\n%-14.14s %10d     %10d   %10d Overdrawn\n",
			devname, grp_quota, grp_used, -grp_free);
   else
       fprintf(out_file, "\n%-14.14s %10d     %10d   %10d\n",
			devname, grp_quota, grp_used, grp_free);
   fprintf(out_file, "%54.54s\n", UNDERLINE);
  }
}

