errx(1, tmpfil);
errx(1, "%s", tmpfil);
} *getprivs __P((u_int, int));#define	FOUND	0x01void	putprivs __P((long, int, struct quotause *));void	freeprivs __P((struct quotause *));int	writetimes __P((struct quotause *, int, int));int	editit __P((char *));int	readtimes __P((struct quotause *, int));int	writeprivs __P((struct quotause *, int, char *, int));int	alldigits __P((char *s));int	readprivs __P((struct quotause *, int));int	hasquota __P((struct fstab *, int, char **));int	cvtatos __P((time_t, char *, time_t *));int	getentry __P((char *, int, u_int *));voidusage(){	(void)fprintf(stderr, "%s%s%s%s",		"Usage: edquota [-u] [-p username] username ...\n",		"\tedquota -g [-p groupname] groupname ...\n",		"\tedquota [-u] -t\n", "\tedquota -g -t\n");	exit(1);}intmain(argc, argv)	register char **argv;	int argc;{	register struct quotause *qup, *protoprivs, *curprivs;	u_int id, protoid;	register int quotatype, tmpfd;	char *protoname = NULL;	int ch;	int tflag = 0, pflag = 0;	if (argc < 2)		usage();	if (getuid())		errx(1, strerror(EPERM));	quotatype = USRQUOTA;	while ((ch = getopt(argc, argv, "ugtp:")) != -1) {		switch(ch) {		case 'p':			protoname = optarg;			pflag++;			break;		case 'g':			quotatype = GRPQUOTA;			break;		case 'u':			quotatype = USRQUOTA;			break;		case 't':			tflag++;			break;		default:			usage();		}	}	argc -= optind;	argv += optind;	if (pflag) {		if (getentry(protoname, quotatype, &protoid) == -1)			exit(1);		protoprivs = getprivs(protoid, quotatype);		for (qup = protoprivs; qup; qup = qup->next) {			qup->dqblk.dqb_btime = 0;			qup->dqblk.dqb_itime = 0;		}		while (argc-- > 0) {			if (getentry(*argv++, quotatype, &id) == -1)				continue;			putprivs(id, quotatype, protoprivs);		}		exit(0);	}	if ((tmpfd = mkstemp(tmpfil)) == -1)		errx(1, tmpfil);	if (tflag) {		protoprivs = getprivs(0, quotatype);		if (writetimes(protoprivs, tmpfd, quotatype) == 0) {			unlink(tmpfil);			exit(1);		}		if (editit(tmpfil) && readtimes(protoprivs, tmpfd))			putprivs(0, quotatype, protoprivs);		freeprivs(protoprivs);		unlink(tmpfil);		exit(0);	}	for ( ; argc > 0; argc--, argv++) {		if (getentry(*argv, quotatype, &id) == -1)			continue;		curprivs = getprivs(id, quotatype);		if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)			continue;		if (editit(tmpfil) && readprivs(curprivs, tmpfd))			putprivs(id, quotatype, curprivs);		freeprivs(curprivs);	}	close(tmpfd);	unlink(tmpfil);	exit(0);}/* * This routine converts a name for a particular quota type to * an identifier. This routine must agree with the kernel routine * getinoquota as to the interpretation of quota types. */intgetentry(name, quotatype, idp)	char *name;	int quotatype;	u_int *idp;{	struct passwd *pw;	struct group *gr;	u_int id;	switch(quotatype) {	case USRQUOTA:		if ((pw = getpwnam(name))) {			*idp = pw->pw_uid;			return 0;		} else if (alldigits(name)) {			if ((id = strtoul(name, NULL, 10)) <= UID_MAX) {				*idp = id;				return 0;			}		}		warnx("%s: no such user", name);		break;	case GRPQUOTA:		if ((gr = getgrnam(name))) {			*idp = gr->gr_gid;			return 0;		} else if (alldigits(name)) {			if ((id = strtoul(name, NULL, 10)) <= GID_MAX) {				*idp = id;				return (0);			}		}		warnx("%s: no such group", name);		break;	default:		warnx("%d: unknown quota type", quotatype);		break;	}	sleep(1);	return(-1);}/* * Collect the requested quota information. */struct quotause *getprivs(id, quotatype)	register u_int id;	int quotatype;{	register struct fstab *fs;	register struct quotause *qup, *quptail;	struct quotause *quphead;	int qcmd, qupsize, fd;	u_int mid;	char *qfpathname;	static int warned = 0;	setfsent();	quphead = (struct quotause *)0;	qcmd = QCMD(Q_GETQUOTA, quotatype);	while ((fs = getfsent())) {		if (strcmp(fs->fs_vfstype, "ffs") &&		    strcmp(fs->fs_vfstype, "ufs") &&		    strcmp(fs->fs_vfstype, "mfs"))			continue;		if (!hasquota(fs, quotatype, &qfpathname))			continue;		qupsize = sizeof(*qup) + strlen(qfpathname);		if ((qup = (struct quotause *)malloc(qupsize)) == NULL)			errx(2, "out of memory");		if (quotactl(fs->fs_file, qcmd, id, (char *)&qup->dqblk) != 0) {	    		if (errno == EOPNOTSUPP && !warned) {				warned++;				(void)fprintf(stderr, "Warning: %s\n",				    "Quotas are not compiled into this kernel");				sleep(3);			}			if (getentry(quotagroup, GRPQUOTA, &mid) == -1) {				warned++;				(void)fprintf(stderr, "Warning: "				    "group %s not known, skipping %s\n",				    quotagroup, fs->fs_file);			}			if ((fd = open(qfpathname, O_RDONLY)) < 0) {				fd = open(qfpathname, O_RDWR|O_CREAT, 0640);				if (fd < 0 && errno != ENOENT) {					perror(qfpathname);					free(qup);					continue;				}				(void)fprintf(stderr, "Creating quota file %s\n",				    qfpathname);				sleep(3);				(void)fchown(fd, getuid(), mid);				(void)fchmod(fd, 0640);			}			lseek(fd, (off_t)(id * sizeof(struct dqblk)), SEEK_SET);			switch (read(fd, &qup->dqblk, sizeof(struct dqblk))) {			case 0:			/* EOF */				/*				 * Convert implicit 0 quota (EOF)				 * into an explicit one (zero'ed dqblk)				 */				bzero((caddr_t)&qup->dqblk,				    sizeof(struct dqblk));				break;			case sizeof(struct dqblk):	/* OK */				break;			default:		/* ERROR */				warn("read error in %s", qfpathname);				close(fd);				free(qup);				continue;			}			close(fd);		}		strcpy(qup->qfname, qfpathname);		strcpy(qup->fsname, fs->fs_file);		if (quphead == NULL)			quphead = qup;		else			quptail->next = qup;		quptail = qup;		qup->next = 0;	}	endfsent();	return(quphead);}