/*
 * Copyright (c) 1980, 1990 Regents of the University of California. All
 * rights reserved.
 * 
 * This code is derived from software contributed to Berkeley by Robert Elz at
 * The University of Melbourne.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: 1. Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer. 2.
 * Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution. 3. All advertising
 * materials mentioning features or use of this software must display the
 * following acknowledgement: This product includes software developed by the
 * University of California, Berkeley and its contributors. 4. Neither the
 * name of the University nor the names of its contributors may be used to
 * endorse or promote products derived from this software without specific
 * prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980, 1990 Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char rcsid[] = "$Id: edquota.c,v 1.11 2000/09/05 18:47:15 mvw Exp mvw $";
#endif /* not lint */

/*
 * Disk quota editor.
 */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/quota.h>
#include <errno.h>
#include <mntent.h>
#include <pwd.h>
#include <grp.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <quotaops.h>
#include <paths.h>

#include "pot.h"

static char *qfextension[] = INITQFNAMES;
static char tmpfil[] = _PATH_TMP "EdP.aXXXXXX";

#define   FOUND   0x01

static int getentry(char *name, int quotatype)
{
   struct passwd  *pw;
   struct group   *gr;
   
   switch (quotatype) {
      case USRQUOTA:
         if (pw = getpwnam(name))
            return (pw->pw_uid);
         fprintf(stderr, _("%s: no such user\n"), name);
         break;
      case GRPQUOTA:
         if (gr = getgrnam(name))
            return (gr->gr_gid);
         fprintf(stderr, _("%s: no such group\n"), name);
         break;
      default:
         fprintf(stderr, _("%d: unknown quota type\n"), quotatype);
         break;
   }
   return (-1);
}

main(int argc, char **argv)
{
   struct quotause *qup, *protoprivs, *curprivs, *pprivs, *cprivs;
   extern char *optarg;
   extern int optind;
   long id, protoid;
   int quotatype, tmpfd;
   char *protoname, ch;
   int tflag = 0, pflag = 0, nflag = 0;
    
   gettexton();
   
   if (argc < 2)
      usage();

   quotatype = USRQUOTA;
#if defined(RPC_SETQUOTA)
   while ((ch = getopt(argc, argv, "ugntp:")) != EOF) {
#else
   while ((ch = getopt(argc, argv, "ugtp:")) != EOF) {
#endif
      switch (ch) {
      case 'p':
         protoname = optarg;
         pflag++;
         break;
      case 'g':
         quotatype = GRPQUOTA;
         break;
#if defined(RPC_SETQUOTA)
      case 'n':
         nflag++;
         break;
#endif
      case 'u':
         quotatype = USRQUOTA;
         break;
      case 't':
         tflag++;
         break;
      default:
         usage();
      }
   }
   argc -= optind;
   argv += optind;

   if (tflag && argc != 0)
      usage();

   if (pflag) {
      if ((protoid = getentry(protoname, quotatype)) == -1)
         exit(1);
      protoprivs = getprivs(protoid, quotatype, (nflag == 0));
      for (qup = protoprivs; qup; qup = qup->next) {
         qup->dqblk.dqb_btime = 0;
         qup->dqblk.dqb_itime = 0;
      }
      while (argc-- > 0) {
         if ((id = getentry(*argv++, quotatype)) < 0)
            continue;
         curprivs = getprivs(id, quotatype, (nflag == 0));

	 for (pprivs = protoprivs, cprivs = curprivs;
	      pprivs && cprivs;
	      pprivs = pprivs->next, cprivs = cprivs->next) {
	    if (strcmp(pprivs->fsname, cprivs->fsname)) {
	       fprintf(stderr, _("fsname mismatch\n"));
	    } else {
	       pprivs->dqblk.dqb_curblocks = cprivs->dqblk.dqb_curblocks;
	       pprivs->dqblk.dqb_curinodes = cprivs->dqblk.dqb_curinodes;
	    }
	 }
         putprivs(id, quotatype, protoprivs);
      }
      exit(0);
   }

   umask(077);
   tmpfd = mkstemp(tmpfil);
   fchown(tmpfd, getuid(), getgid());
   if (tflag) {
      protoprivs = getprivs(0, quotatype, (nflag == 0));
      if (writetimes(protoprivs, tmpfd, quotatype) == 0)
         exit(1);
      if (editprivs(tmpfil) && readtimes(protoprivs, tmpfd))
         putprivs(0, quotatype, protoprivs);
      freeprivs(protoprivs);
      close(tmpfd);
      unlink(tmpfil);
   } else {
      for (; argc > 0; argc--, argv++) {
         if ((id = getentry(*argv, quotatype)) == -1)
            continue;
         curprivs = getprivs(id, quotatype, (nflag == 0));
         if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)
            continue;
         if (editprivs(tmpfil) && readprivs(curprivs, tmpfd))
            putprivs(id, quotatype, curprivs);
         freeprivs(curprivs);
      }
   }

   close(tmpfd);
   unlink(tmpfil);
   exit(0);
}

usage(void)
{
#if defined(RPC_SETQUOTA)
   fprintf(stderr, "%s%s%s%s",
      _("Usage:\tedquota [-n] [-u] [-p username] username ...\n"),
      _("\tedquota [-n] -g [-p groupname] groupname ...\n"),
      _("\tedquota [-n] [-u] -t\n"), _("\tedquota [-n] -g -t\n"));
#else
   fprintf(stderr, "%s%s%s%s",
      _("Usage:\tedquota [-u] [-p username] username ...\n"),
      _("\tedquota -g [-p groupname] groupname ...\n"),
      _("\tedquota [-u] -t\n"), _("\tedquota -g -t\n"));
#endif
   exit(1);
}
