Exemplo n.º 1
0
int
main(int argc, char **argv)
{
	int ch;
	int error = 0;
	const char *errstr;
	extern char *__progname;

	if (pledge("stdio rpath wpath cpath getpw flock", NULL) == -1)
		err(1, "pledge");

	while ((ch = getopt(argc, argv, "abcdDfijkKlmnqrstuv:")) != -1)
		switch (ch) {
		case 'a':
			/* print all commands */
			aflag = 1;
			break;
		case 'b':
			/* sort by per-call user/system time average */
			bflag = 1;
			sa_cmp = cmp_avgusrsys;
			break;
		case 'c':
			/* print percentage total time */
			cflag = 1;
			break;
		case 'd':
			/* sort by averge number of disk I/O ops */
			dflag = 1;
			sa_cmp = cmp_avgdkio;
			break;
		case 'D':
			/* print and sort by total disk I/O ops */
			Dflag = 1;
			sa_cmp = cmp_dkio;
			break;
		case 'f':
			/* force no interactive threshold comprison */
			fflag = 1;
			break;
		case 'i':
			/* do not read in summary file */
			iflag = 1;
			break;
		case 'j':
			/* instead of total minutes, give sec/call */
			jflag = 1;
			break;
		case 'k':
			/* sort by cpu-time average memory usage */
			kflag = 1;
			sa_cmp = cmp_avgcpumem;
			break;
		case 'K':
			/* print and sort by cpu-storage integral */
			sa_cmp = cmp_cpumem;
			Kflag = 1;
			break;
		case 'l':
			/* separate system and user time */
			lflag = 1;
			break;
		case 'm':
			/* print procs and time per-user */
			mflag = 1;
			break;
		case 'n':
			/* sort by number of calls */
			sa_cmp = cmp_calls;
			break;
		case 'q':
			/* quiet; error messages only */
			qflag = 1;
			break;
		case 'r':
			/* reverse order of sort */
			rflag = 1;
			break;
		case 's':
			/* merge accounting file into summaries */
			sflag = 1;
			break;
		case 't':
			/* report ratio of user and system times */
			tflag = 1;
			break;
		case 'u':
			/* first, print uid and command name */
			uflag = 1;
			break;
		case 'v':
			/* cull junk */
			vflag = 1;
			/* XXX cutoff could be converted to quad_t? */
			cutoff = strtonum(optarg, 1, INT_MAX, &errstr);
			if (errstr)
				errx(1, "-v %s: %s", optarg, errstr);
			break;
		case '?':
		default:
			(void)fprintf(stderr,
			    "usage: %s [-abcDdfijKklmnqrstu] [-v cutoff]"
			    " [file ...]\n", __progname);
			exit(1);
		}

	argc -= optind;
	argv += optind;

	/* various argument checking */
	if (fflag && !vflag)
		errx(1, "only one of -f requires -v");
	if (fflag && aflag)
		errx(1, "only one of -a and -v may be specified");
	/* XXX need more argument checking */

	if (!uflag) {
		/* initialize tables */
		if ((sflag || (!mflag && !qflag)) && pacct_init() != 0)
			errx(1, "process accounting initialization failed");
		if ((sflag || (mflag && !qflag)) && usracct_init() != 0)
			errx(1, "user accounting initialization failed");
	}

	if (argc == 0) {
		argc = dfltargc;
		argv = dfltargv;
	}

	/* for each file specified */
	for (; argc > 0; argc--, argv++) {
		int	fd;

		/*
		 * load the accounting data from the file.
		 * if it fails, go on to the next file.
		 */
		fd = acct_load(argv[0], sflag);
		if (fd < 0)
			continue;

		if (!uflag && sflag) {
#ifndef DEBUG
			sigset_t nmask, omask;
			int unmask = 1;

			/*
			 * block most signals so we aren't interrupted during
			 * the update.
			 */
			if (sigfillset(&nmask) == -1) {
				warn("sigfillset");
				unmask = 0;
				error = 1;
			}
			if (unmask &&
			    (sigprocmask(SIG_BLOCK, &nmask, &omask) == -1)) {
				warn("couldn't set signal mask ");
				unmask = 0;
				error = 1;
			}
#endif /* DEBUG */

			/*
			 * truncate the accounting data file ASAP, to avoid
			 * losing data.  don't worry about errors in updating
			 * the saved stats; better to underbill than overbill,
			 * but we want every accounting record intact.
			 */
			if (ftruncate(fd, 0) == -1) {
				warn("couldn't truncate %s", *argv);
				error = 1;
			}

			/*
			 * update saved user and process accounting data.
			 * note errors for later.
			 */
			if (pacct_update() != 0 || usracct_update() != 0)
				error = 1;

#ifndef DEBUG
			/*
			 * restore signals
			 */
			if (unmask &&
			    (sigprocmask(SIG_SETMASK, &omask, NULL) == -1)) {
				warn("couldn't restore signal mask");
				error = 1;
			}
#endif /* DEBUG */
		}

		/*
		 * close the opened accounting file
		 */
		if (close(fd) == -1) {
			warn("close %s", *argv);
			error = 1;
		}
	}

	if (!uflag && !qflag) {
		/* print any results we may have obtained. */
		if (!mflag)
			pacct_print();
		else
			usracct_print();
	}

	if (!uflag) {
		/* finally, deallocate databases */
		if (sflag || (!mflag && !qflag))
			pacct_destroy();
		if (sflag || (mflag && !qflag))
			usracct_destroy();
	}

	exit(error);
}
Exemplo n.º 2
0
int
usracct_init(void)
{
	DB *saved_usracct_db;
	BTREEINFO bti;
	int error;
	int ndups = 0;

	memset(&bti, 0, sizeof(bti));
	bti.compare = uid_compare;

	usracct_db = dbopen(NULL, O_RDWR|O_CREAT|O_TRUNC, 0644, DB_BTREE, &bti);
	if (usracct_db == NULL)
		return (-1);

	error = 0;
	if (!iflag) {
		DBT key, data;
		int serr, nerr;

		saved_usracct_db = dbopen(_PATH_USRACCT, O_RDONLY, 0, DB_BTREE,
		    &bti);
		if (saved_usracct_db == NULL) {
			error = (errno == ENOENT) ? 0 : -1;
			if (error)
				warn("retrieving user accounting summary");
			goto out;
		}

		serr = DB_SEQ(saved_usracct_db, &key, &data, R_FIRST);
		if (serr < 0) {
			warn("retrieving user accounting summary");
			error = -1;
			goto closeout;
		}
		while (serr == 0) {
			nerr = DB_PUT(usracct_db, &key, &data, R_NOOVERWRITE);
			if (nerr < 0) {
				warn("initializing user accounting stats");
				error = -1;
				break;
			} 
			if (nerr == 1) {
				warnx("duplicate key in `%s': %s",
				    _PATH_USRACCT, fmt(&key));
				if (ndups++ == 5) {
					warnx("too many duplicate keys;"
					    " `%s' possibly corrupted.",
					    _PATH_USRACCT);
					error = -1;
					break;
				}
			}

			serr = DB_SEQ(saved_usracct_db, &key, &data, R_NEXT);
			if (serr < 0) {
				warn("retrieving user accounting summary");
				error = -1;
				break;
			}
		}

closeout:
		if (DB_CLOSE(saved_usracct_db) < 0) {
			warn("closing user accounting summary");
			error = -1;
		}
	}

out:
	if (error != 0)
		usracct_destroy();
	return (error);
}