Exemple #1
0
static int
edit(void)
{
	int c, fd;
	struct disklabel label;
	FILE *fp;

	if ((fd = mkstemp(tmpfil)) == -1 ||
	    (fp = fdopen(fd, "w")) == NULL) {
		warnx("can't create %s", tmpfil);
		return (1);
	}
	display(fp, NULL);
	fclose(fp);
	for (;;) {
		if (!editit())
			break;
		fp = fopen(tmpfil, "r");
		if (fp == NULL) {
			warnx("can't reopen %s for reading", tmpfil);
			break;
		}
		bzero((char *)&label, sizeof(label));
		c = getasciilabel(fp, &label);
		fclose(fp);
		if (c) {
			lab = label;
			if (writelabel() == 0) {
				(void) unlink(tmpfil);
				return (0);
			}
		}
		printf("re-edit the label? [y]: ");
		fflush(stdout);
		c = getchar();
		if (c != EOF && c != (int)'\n')
			while (getchar() != (int)'\n')
				;
		if  (c == (int)'n')
			break;
	}
	(void) unlink(tmpfil);
	return (1);
}
Exemple #2
0
int
edit(struct disklabel *lp, int f)
{
	int first, ch, fd, error = 0;
	struct disklabel label;
	FILE *fp;
	u_int64_t total_sectors, starting_sector, ending_sector;

	if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) {
		if (fd != -1)
			close(fd);
		warn("%s", tmpfil);
		return (1);
	}
	display(fp, lp, 0, 1);
	fprintf(fp, "\n# Notes:\n");
	fprintf(fp,
"# Up to 16 partitions are valid, named from 'a' to 'p'.  Partition 'a' is\n"
"# your root filesystem, 'b' is your swap, and 'c' should cover your whole\n"
"# disk. Any other partition is free for any use.  'size' and 'offset' are\n"
"# in 512-byte blocks. fstype should be '4.2BSD', 'swap', or 'none' or some\n"
"# other values.  fsize/bsize/cpg should typically be '2048 16384 16' for a\n"
"# 4.2BSD filesystem (or '512 4096 16' except on alpha, sun4, ...)\n");
	fclose(fp);
	for (;;) {
		if (editit(tmpfil) == -1)
			break;
		fp = fopen(tmpfil, "r");
		if (fp == NULL) {
			warn("%s", tmpfil);
			break;
		}
		/* Get values set by OS and not the label. */
		if (ioctl(f, DIOCGPDINFO, &label) < 0)
			err(4, "ioctl DIOCGPDINFO");
		ending_sector = DL_GETBEND(&label);
		starting_sector = DL_GETBSTART(&label);
		total_sectors = DL_GETDSIZE(&label);
		memset(&label, 0, sizeof(label));
		error = getasciilabel(fp, &label);
		DL_SETBEND(&label, ending_sector);
		DL_SETBSTART(&label, starting_sector);
		DL_SETDSIZE(&label, total_sectors);

		if (error == 0) {
			if (cmplabel(lp, &label) == 0) {
				puts("No changes.");
				fclose(fp);
				(void) unlink(tmpfil);
				return (0);
			}
			*lp = label;
			if (writelabel(f, bootarea, lp) == 0) {
				fclose(fp);
				(void) unlink(tmpfil);
				return (0);
			}
		}
		fclose(fp);
		printf("re-edit the label? [y]: ");
		fflush(stdout);
		first = ch = getchar();
		while (ch != '\n' && ch != EOF)
			ch = getchar();
		if (first == 'n' || first == 'N')
			break;
	}
	(void)unlink(tmpfil);
	return (1);
}
Exemple #3
0
/*
 * Parse edit command.  Returns 0 on success, -1 on error.
 */
int
eparse(const char *cmd, const char *left, const char *right)
{
	FILE *file;
	size_t nread;
	int fd;
	char *filename;
	char buf[BUFSIZ], *text;

	/* Skip whitespace. */
	while (isspace(*cmd))
		++cmd;

	text = NULL;
	switch (*cmd) {
	case '\0':
		/* Edit empty file. */
		break;

	case 'b':
		/* Both strings. */
		if (left == NULL)
			goto RIGHT;
		if (right == NULL)
			goto LEFT;

		/* Neither column is blank, so print both. */
		if (asprintf(&text, "%s\n%s\n", left, right) == -1)
			err(2, "could not allocate memory");
		break;

	case 'l':
LEFT:
		/* Skip if there is no left column. */
		if (left == NULL)
			break;

		if (asprintf(&text, "%s\n", left) == -1)
			err(2, "could not allocate memory");

		break;

	case 'r':
RIGHT:
		/* Skip if there is no right column. */
		if (right == NULL)
			break;

		if (asprintf(&text, "%s\n", right) == -1)
			err(2, "could not allocate memory");

		break;

	default:
		return (-1);
	}

	/* Create temp file. */
	if (asprintf(&filename, "%s/sdiff.XXXXXXXXXX", tmpdir) == -1)
		err(2, "asprintf");
	if ((fd = mkstemp(filename)) == -1)
		err(2, "mkstemp");
	if (text != NULL) {
		size_t len;
		ssize_t nwritten;

		len = strlen(text);
		if ((nwritten = write(fd, text, len)) == -1 ||
		    (size_t)nwritten != len) {
			warn("error writing to temp file");
			cleanup(filename);
		}
	}
	close(fd);

	/* text is no longer used. */
	free(text);

	/* Edit temp file. */
	if (editit(filename) == -1) {
		warn("error editing %s", filename);
		cleanup(filename);
	}

	/* Open temporary file. */
	if (!(file = fopen(filename, "r"))) {
		warn("could not open edited file: %s", filename);
		cleanup(filename);
	}

	/* Copy temporary file contents to output file. */
	for (nread = sizeof(buf); nread == sizeof(buf);) {
		size_t nwritten;

		nread = fread(buf, sizeof(*buf), sizeof(buf), file);
		/* Test for error or end of file. */
		if (nread != sizeof(buf) &&
		    (ferror(file) || !feof(file))) {
			warnx("error reading edited file: %s", filename);
			cleanup(filename);
		}

		/*
		 * If we have nothing to read, break out of loop
		 * instead of writing nothing.
		 */
		if (!nread)
			break;

		/* Write data we just read. */
		nwritten = fwrite(buf, sizeof(*buf), nread, outfp);
		if (nwritten != nread) {
			warnx("error writing to output file");
			cleanup(filename);
		}
	}

	/* We've reached the end of the temporary file, so remove it. */
	if (unlink(filename))
		warn("could not delete: %s", filename);
	fclose(file);

	free(filename);

	return (0);
}
Exemple #4
0
/*
 * Run an editor on the file at "fpp" of "size" bytes,
 * and return a new file pointer.
 * Signals must be handled by the caller.
 * "Type" is 'e' for _PATH_EX, 'v' for _PATH_VI.
 */
FILE *
run_editor(FILE *fp, off_t size, int type, int readonly)
{
	FILE *nf = NULL;
	int t;
	time_t modtime;
	char *edit, tempname[PATHSIZE];
	struct stat statb;

	(void)snprintf(tempname, sizeof(tempname),
	    "%s/mail.ReXXXXXXXXXX", tmpdir);
	if ((t = mkstemp(tempname)) == -1 ||
	    (nf = Fdopen(t, "w")) == NULL) {
		warn("%s", tempname);
		goto out;
	}
	if (readonly && fchmod(t, 0400) == -1) {
		warn("%s", tempname);
		(void)rm(tempname);
		goto out;
	}
	if (size >= 0)
		while (--size >= 0 && (t = getc(fp)) != EOF)
			(void)putc(t, nf);
	else
		while ((t = getc(fp)) != EOF)
			(void)putc(t, nf);
	(void)fflush(nf);
	if (fstat(fileno(nf), &statb) < 0)
		modtime = 0;
	else
		modtime = statb.st_mtime;
	if (ferror(nf)) {
		(void)Fclose(nf);
		warn("%s", tempname);
		(void)rm(tempname);
		nf = NULL;
		goto out;
	}
	if (Fclose(nf) < 0) {
		warn("%s", tempname);
		(void)rm(tempname);
		nf = NULL;
		goto out;
	}
	nf = NULL;
	if (type == 'e') {
		edit = value("EDITOR");
		if (edit == NULL || edit[0] == '\0')
			edit = _PATH_EX;
	} else {
		edit = value("VISUAL");
		if (edit == NULL || edit[0] == '\0')
			edit = _PATH_VI;
	}
	if (editit(edit, tempname) == -1) {
		(void)rm(tempname);
		goto out;
	}
	/*
	 * If in read only mode or file unchanged, just remove the editor
	 * temporary and return.
	 */
	if (readonly) {
		(void)rm(tempname);
		goto out;
	}
	if (stat(tempname, &statb) < 0) {
		warn("%s", tempname);
		goto out;
	}
	if (modtime == statb.st_mtime) {
		(void)rm(tempname);
		goto out;
	}
	/*
	 * Now switch to new file.
	 */
	if ((nf = Fopen(tempname, "a+")) == NULL) {
		warn("%s", tempname);
		(void)rm(tempname);
		goto out;
	}
	(void)rm(tempname);
out:
	return(nf);
}
Exemple #5
0
static void
mode_edit(int fd, int page, int edit, int argc, char *argv[])
{
	int i;
	u_char data[255];
	u_char *mode_pars;
	struct mode_header
	{
		u_char mdl;	/* Mode data length */
		u_char medium_type;
		u_char dev_spec_par;
		u_char bdl;	/* Block descriptor length */
	};

	struct mode_page_header
	{
		u_char page_code;
		u_char page_length;
	};

	struct mode_header *mh;
	struct mode_page_header *mph;

	char *fmt = mode_lookup(page);
	if (!fmt && verbose) {
		fprintf(stderr,
		"No mode data base entry in \"%s\" for page %d;  binary %s only.\n",
		mode_db, page, (edit ? "edit" : "display"));
	}

	if (edit) {
		if (!fmt) {
			fprintf(stderr, "Sorry: can't edit without a format.\n");
			exit(1);
		}

		if (pagectl != 0 && pagectl != 3) {
			fprintf(stderr,
"It only makes sense to edit page 0 (current) or page 3 (saved values)\n");
			exit(1);
		}

		verbose = 1;

		mode_sense(fd, data, sizeof(data), 1, page);

		mh = (struct mode_header *)data;
		mph = (struct mode_page_header *)
		(((char *)mh) + sizeof(*mh) + mh->bdl);

		mode_pars = (char *)mph + sizeof(*mph);

		edit_init();
		scsireq_buff_decode_visit(mode_pars, mh->mdl,
		fmt, edit_check, 0);

		mode_sense(fd, data, sizeof(data), 0, page);

		edit_rewind();
		scsireq_buff_decode_visit(mode_pars, mh->mdl,
		fmt, edit_defaults, 0);

		edit_rewind();
		scsireq_buff_decode_visit(mode_pars, mh->mdl,
		fmt, edit_report, 0);

		fclose(edit_file);
		if (editit(edit_name) == -1 && errno != ECHILD)
			err(1, "edit %s", edit_name);
		if ((edit_file = fopen(edit_name, "r")) == NULL)
			err(1, "open %s", edit_name);

		edit_rewind();
		scsireq_buff_encode_visit(mode_pars, mh->mdl,
		fmt, edit_get, 0);

		/* Eliminate block descriptors:
		 */
		bcopy((char *)mph, ((char *)mh) + sizeof(*mh),
		sizeof(*mph) + mph->page_length);

		mh->bdl = 0;
		mph = (struct mode_page_header *) (((char *)mh) + sizeof(*mh));
		mode_pars = ((char *)mph) + 2;

#if 0
		/* Turn this on to see what you're sending to the
		 * device:
		 */
		edit_rewind();
		scsireq_buff_decode_visit(mode_pars,
		mh->mdl, fmt, arg_put, 0);
#endif

		edit_done();

		/* Make it permanent if pageselect is three.
		 */

		mph->page_code &= ~0xC0;	/* Clear PS and RESERVED */
		mh->mdl = 0;				/* Reserved for mode select */

		mode_select(fd, (char *)mh,
		sizeof(*mh) + mh->bdl + sizeof(*mph) + mph->page_length,
		(pagectl == 3));

		exit(0);
	}

	mode_sense(fd, data, sizeof(data), pagectl, page);

	/* Skip over the block descriptors.
	 */
	mh = (struct mode_header *)data;
	mph = (struct mode_page_header *)(((char *)mh) + sizeof(*mh) + mh->bdl);
	mode_pars = (char *)mph + sizeof(*mph);

	if (!fmt) {
		for (i = 0; i < mh->mdl; i++) {
			printf("%02x%c",mode_pars[i],
			(((i + 1) % 8) == 0) ? '\n' : ' ');
		}
		putc('\n', stdout);
	} else {
			verbose = 1;
			scsireq_buff_decode_visit(mode_pars,
			mh->mdl, fmt, arg_put, 0);
	}
}
Exemple #6
0
int
main(int argc, char **argv)
{
	struct quotause *qup, *protoprivs, *curprivs;
	long id, protoid;
	long long lim;
	int i, quotatype, range, tmpfd;
	uid_t startuid, enduid;
	u_int32_t *limp;
	char *protoname, *cp, *oldoptarg, ch;
	int eflag = 0, tflag = 0, pflag = 0;
	char *fspath = NULL;
	char buf[MAXLOGNAME];

	if (argc < 2)
		usage();
	if (getuid())
		errx(1, "permission denied");
	quotatype = USRQUOTA;
	protoprivs = NULL;
	curprivs = NULL;
	protoname = NULL;
	while ((ch = getopt(argc, argv, "ugtf:p:e:")) != -1) {
		switch(ch) {
		case 'f':
			fspath = optarg;
			break;
		case 'p':
			protoname = optarg;
			pflag++;
			break;
		case 'g':
			quotatype = GRPQUOTA;
			break;
		case 'u':
			quotatype = USRQUOTA;
			break;
		case 't':
			tflag++;
			break;
		case 'e':
			if ((qup = malloc(sizeof(*qup))) == NULL)
				errx(2, "out of memory");
			bzero(qup, sizeof(*qup));
			i = 0;
			oldoptarg = optarg;
			for (cp = optarg; (cp = strsep(&optarg, ":")) != NULL;
			    i++) {
				if (cp != oldoptarg)
					*(cp - 1) = ':';
				limp = NULL;
				switch (i) {
				case 0:
					strlcpy(qup->fsname, cp,
					    sizeof(qup->fsname));
					break;
				case 1:
					limp = &qup->dqblk.dqb_bsoftlimit;
					break;
				case 2:
					limp = &qup->dqblk.dqb_bhardlimit;
					break;
				case 3:
					limp = &qup->dqblk.dqb_isoftlimit;
					break;
				case 4:
					limp = &qup->dqblk.dqb_ihardlimit;
					break;
				default:
					warnx("incorrect quota specification: "
					    "%s", oldoptarg);
					usage();
					break; /* XXX: report an error */
				}
				if (limp != NULL) {
					lim = strtoll(cp, NULL, 10);
					if (lim < 0 || lim > UINT_MAX)
						errx(1, "invalid limit value: "
						    "%lld", lim);
					*limp = (u_int32_t)lim;
				}
			}
			qup->dqblk.dqb_bsoftlimit =
			    btodb((off_t)qup->dqblk.dqb_bsoftlimit * 1024);
			qup->dqblk.dqb_bhardlimit =
			    btodb((off_t)qup->dqblk.dqb_bhardlimit * 1024);
			if (protoprivs == NULL) {
				protoprivs = curprivs = qup;
			} else {
				curprivs->next = qup;
				curprivs = qup;
			}
			eflag++;
			pflag++;
			break;
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;
	if (pflag) {
		if (protoprivs == NULL) {
			if ((protoid = getentry(protoname, quotatype)) == -1)
				exit(1);
			protoprivs = getprivs(protoid, quotatype, fspath);
			for (qup = protoprivs; qup; qup = qup->next) {
				qup->dqblk.dqb_btime = 0;
				qup->dqblk.dqb_itime = 0;
			}
		}
		for (; argc-- > 0; argv++) {
			if (strspn(*argv, "0123456789-") == strlen(*argv) &&
			    (cp = strchr(*argv, '-')) != NULL) {
				*cp++ = '\0';
				startuid = atoi(*argv);
				enduid = atoi(cp);
				if (enduid < startuid)
					errx(1,
	"ending uid (%d) must be >= starting uid (%d) when using uid ranges",
						enduid, startuid);
				range = 1;
			} else {
				startuid = enduid = 0;
				range = 0;
			}
			for ( ; startuid <= enduid; startuid++) {
				if (range)
					snprintf(buf, sizeof(buf), "%d",
					    startuid);
				else
					snprintf(buf, sizeof(buf), "%s",
						*argv);
				if ((id = getentry(buf, quotatype)) < 0)
					continue;
				if (eflag) {
					for (qup = protoprivs; qup;
					    qup = qup->next) {
						curprivs = getprivs(id,
						    quotatype, qup->fsname);
						if (curprivs == NULL)
							continue;
						strcpy(qup->qfname,
						    curprivs->qfname);
						strcpy(qup->fsname,
						    curprivs->fsname);
					}
				}
				putprivs(id, quotatype, protoprivs);						
			}
		}
		exit(0);
	}
	tmpfd = mkstemp(tmpfil);
	fchown(tmpfd, getuid(), getgid());
	if (tflag) {
		protoprivs = getprivs(0, quotatype, fspath);
		if (writetimes(protoprivs, tmpfd, quotatype) == 0)
			exit(1);
		if (editit(tmpfil) && readtimes(protoprivs, tmpfil))
			putprivs(0, quotatype, protoprivs);
		freeprivs(protoprivs);
		close(tmpfd);
		unlink(tmpfil);
		exit(0);
	}
	for ( ; argc > 0; argc--, argv++) {
		if ((id = getentry(*argv, quotatype)) == -1)
			continue;
		curprivs = getprivs(id, quotatype, fspath);
		if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)
			continue;
		if (editit(tmpfil) && readprivs(curprivs, tmpfil))
			putprivs(id, quotatype, curprivs);
		freeprivs(curprivs);
	}
	close(tmpfd);
	unlink(tmpfil);
	exit(0);
}
Exemple #7
0
int
main(int argc, char **argv)
{
	uid_t	uid;
	char	*basename;
	int	opt;
	int	i;
	int	tmpfd = -1;

	basename = argv[0];
	if (argc < 2) {
		usage();
	}
	if (quotactl(Q_SYNC, (char *)NULL, 0, (caddr_t)NULL) < 0 &&
	    errno == EINVAL) {
		(void) printf("Warning: "
			"Quotas are not compiled into this kernel\n");
		(void) sleep(3);
	}
	if (getuid()) {
		(void) fprintf(stderr, "%s: permission denied\n", basename);
		exit(32);
	}
	setupfs();
	if (fsqlist == NULL) {
		(void) fprintf(stderr, "%s: no UFS filesystems with %s file\n",
		    MNTTAB, QFNAME);
		exit(32);
	}
	tmpfd = mkstemp(tmpfil);
	if (tmpfd == -1 || fchown(tmpfd, getuid(), getgid()) == -1) {
		fprintf(stderr, "failure in temporary file %s\n", tmpfil);
		exit(32);
	}
	(void) close(tmpfd);
	while ((opt = getopt(argc, argv, "p:tV")) != EOF)
		switch (opt) {
		case 't':
			gettimes(0);
			if (editit())
				puttimes(0);
			(void) unlink(tmpfil);
			exit(0);
			/*NOTREACHED*/

		case 'p':
			uid = getentry(optarg);
			if (uid > MAXUID) {
				(void) unlink(tmpfil);
				exit(32);
			}
			getprivs(uid);
			if (optind == argc) {
				(void) unlink(tmpfil);
				usage();
			}
			for (i = optind; i < argc; i++) {
				uid = getentry(argv[i]);
				if (uid > MAXUID) {
					(void) unlink(tmpfil);
					exit(32);
				}
				getdiscq(uid);
				putprivs(uid);
			}
			(void) unlink(tmpfil);
			exit(0);
			/*NOTREACHED*/

		case 'V':		/* Print command line */
			{
				char		*optt;
				int		optc;

				(void) printf("edquota -F UFS");
				for (optc = 1; optc < argc; optc++) {
					optt = argv[optc];
					if (optt)
						(void) printf(" %s ", optt);
				}
				(void) putchar('\n');
			}
			break;

		case '?':
			usage();
		}

	for (i = optind; i < argc; i++) {
		uid = getentry(argv[i]);
		if (uid > MAXUID)
			continue;
		getprivs(uid);
		if (editit())
			putprivs(uid);
		if (uid == 0) {
			(void) printf("edquota: Note that uid 0's quotas "
			    "are used as default values for other users,\n");
			(void) printf("not as a limit on the uid 0 user.\n");
		}
	}
	(void) unlink(tmpfil);
	return (0);
}
int
main(int argc, char *argv[])
{
	struct quotause *qup, *protoprivs, *curprivs;
	u_int id, protoid;
	int quotatype, tmpfd;
	char *protoname = NULL;
	int ch;
	int tflag = 0, pflag = 0;

	if (argc < 2)
		usage();
	if (getuid())
		errx(1, "%s", 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, "%s", tmpfil);
	if (tflag) {
		protoprivs = getprivs(0, quotatype);
		if (writetimes(protoprivs, tmpfd, quotatype) == 0) {
			unlink(tmpfil);
			exit(1);
		}
		if (editit(tmpfil) == -1) {
			unlink(tmpfil);
			err(1, "error starting editor");
		}
		if (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) == -1) {
			warn("error starting editor");
			continue;
		}
		if (readprivs(curprivs, tmpfd))
			putprivs(id, quotatype, curprivs);
		freeprivs(curprivs);
	}
	close(tmpfd);
	unlink(tmpfil);
	exit(0);
}
Exemple #9
0
int
main(int argc, char *argv[])
{
	struct quotause *qup, *protoprivs, *curprivs;
	long id, protoid;
	int i, quotatype, range, tmpfd;
	uid_t startuid, enduid;
	uint64_t lim;
	char *protoname, *cp, *endpt, *oldoptarg;
	int eflag = 0, tflag = 0, pflag = 0, ch;
	char *fspath = NULL;
	char buf[MAXLOGNAME];

	if (argc < 2)
		usage();
	if (getuid())
		errx(1, "permission denied");
	quotatype = USRQUOTA;
	protoprivs = NULL;
	curprivs = NULL;
	protoname = NULL;
	while ((ch = getopt(argc, argv, "ughtf:p:e:")) != -1) {
		switch(ch) {
		case 'f':
			fspath = optarg;
			break;
		case 'p':
			if (eflag) {
				warnx("cannot specify both -e and -p");
				usage();
				/* not reached */
			}
			protoname = optarg;
			pflag++;
			break;
		case 'g':
			quotatype = GRPQUOTA;
			break;
		case 'h':
			hflag++;
			break;
		case 'u':
			quotatype = USRQUOTA;
			break;
		case 't':
			tflag++;
			break;
		case 'e':
			if (pflag) {
				warnx("cannot specify both -e and -p");
				usage();
				/* not reached */
			}
			if ((qup = calloc(1, sizeof(*qup))) == NULL)
				errx(2, "out of memory");
			oldoptarg = optarg;
			for (i = 0, cp = optarg;
			     (cp = strsep(&optarg, ":")) != NULL; i++) {
				if (cp != oldoptarg)
					*(cp - 1) = ':';
				if (i > 0 && !isdigit(*cp)) {
					warnx("incorrect quota specification: "
					    "%s", oldoptarg);
					usage();
					/* Not Reached */
				}
				switch (i) {
				case 0:
					strlcpy(qup->fsname, cp,
					    sizeof(qup->fsname));
					break;
				case 1:
					lim = strtoll(cp, &endpt, 10);
					qup->dqblk.dqb_bsoftlimit =
						cvtblkval(lim, *endpt,
						    "block soft limit");
					continue;
				case 2:
					lim = strtoll(cp, &endpt, 10);
					qup->dqblk.dqb_bhardlimit =
						cvtblkval(lim, *endpt,
						    "block hard limit");
					continue;
				case 3:
					lim = strtoll(cp, &endpt, 10);
					qup->dqblk.dqb_isoftlimit =
						cvtinoval(lim, *endpt,
						    "inode soft limit");
					continue;
				case 4:
					lim = strtoll(cp, &endpt, 10);
					qup->dqblk.dqb_ihardlimit =
						cvtinoval(lim, *endpt,
						    "inode hard limit");
					continue;
				default:
					warnx("incorrect quota specification: "
					    "%s", oldoptarg);
					usage();
					/* Not Reached */
				}
			}
			if (protoprivs == NULL) {
				protoprivs = curprivs = qup;
			} else {
				curprivs->next = qup;
				curprivs = qup;
			}
			eflag++;
			break;
		default:
			usage();
			/* Not Reached */
		}
	}
	argc -= optind;
	argv += optind;
	if (pflag || eflag) {
		if (pflag) {
			if ((protoid = getentry(protoname, quotatype)) == -1)
				exit(1);
			protoprivs = getprivs(protoid, quotatype, fspath);
			if (protoprivs == NULL)
				exit(0);
			for (qup = protoprivs; qup; qup = qup->next) {
				qup->dqblk.dqb_btime = 0;
				qup->dqblk.dqb_itime = 0;
			}
		}
		for (; argc-- > 0; argv++) {
			if (strspn(*argv, "0123456789-") == strlen(*argv) &&
			    (cp = strchr(*argv, '-')) != NULL) {
				*cp++ = '\0';
				startuid = atoi(*argv);
				enduid = atoi(cp);
				if (enduid < startuid)
					errx(1,
	"ending uid (%d) must be >= starting uid (%d) when using uid ranges",
						enduid, startuid);
				range = 1;
			} else {
				startuid = enduid = 0;
				range = 0;
			}
			for ( ; startuid <= enduid; startuid++) {
				if (range)
					snprintf(buf, sizeof(buf), "%d",
					    startuid);
				else
					snprintf(buf, sizeof(buf), "%s",
						*argv);
				if ((id = getentry(buf, quotatype)) < 0)
					continue;
				if (pflag) {
					putprivs(id, protoprivs);
					continue;
				}
				for (qup = protoprivs; qup; qup = qup->next) {
					curprivs = getprivs(id, quotatype,
					    qup->fsname);
					if (curprivs == NULL)
						continue;
					curprivs->dqblk = qup->dqblk;
					putprivs(id, curprivs);
					freeprivs(curprivs);
				}
			}
		}
		if (pflag)
			freeprivs(protoprivs);
		exit(0);
	}
	tmpfd = mkstemp(tmpfil);
	fchown(tmpfd, getuid(), getgid());
	if (tflag) {
		if ((protoprivs = getprivs(0, quotatype, fspath)) != NULL) {
			if (writetimes(protoprivs, tmpfd, quotatype) != 0 &&
			    editit(tmpfil) && readtimes(protoprivs, tmpfil))
				putprivs(0L, protoprivs);
			freeprivs(protoprivs);
		}
		close(tmpfd);
		unlink(tmpfil);
		exit(0);
	}
	for ( ; argc > 0; argc--, argv++) {
		if ((id = getentry(*argv, quotatype)) == -1)
			continue;
		if ((curprivs = getprivs(id, quotatype, fspath)) == NULL)
			exit(1);
		if (writeprivs(curprivs, tmpfd, *argv, quotatype) == 0)
			continue;
		if (editit(tmpfil) && readprivs(curprivs, tmpfil))
			putprivs(id, curprivs);
		freeprivs(curprivs);
	}
	close(tmpfd);
	unlink(tmpfil);
	exit(0);
}