Ejemplo n.º 1
0
/*
 ***************************************************************************
 * Print contents of a special (RESTART or COMMENT) record.
 *
 * IN:
 * @curr		Index in array for current sample statistics.
 * @use_tm_start	Set to TRUE if option -s has been used.
 * @use_tm_end		Set to TRUE if option -e has been used.
 * @rtype		Record type (RESTART or COMMENT).
 * @ifd			Input file descriptor.
 * @rectime		Structure where timestamp (expressed in local time
 *			or in UTC depending on whether options -T/-t have
 * 			been used or not) can be saved for current record.
 * @loctime		Structure where timestamp (expressed in local time)
 *			can be saved for current record.
 * @file		Name of file being read.
 * @tab			Number of tabulations to print.
 * @file_magic		file_magic structure filled with file magic header
 * 			data.
 ***************************************************************************
 */
void print_special_record(int curr, int use_tm_start, int use_tm_end, int rtype, int ifd,
			  struct tm *rectime, struct tm *loctime, char *file, int tab,
			  struct file_magic *file_magic)
{
	char cur_date[32], cur_time[32];
	int dp = 1;
	unsigned int new_cpu_nr;

	/* Fill timestamp structure (rectime) for current record */
	sa_get_record_timestamp_struct(flags, &record_hdr[curr], rectime, loctime);

	/* The record must be in the interval specified by -s/-e options */
	if ((use_tm_start && (datecmp(loctime, &tm_start) < 0)) ||
	    (use_tm_end && (datecmp(loctime, &tm_end) > 0))) {
		/* Will not display the special record */
		dp = 0;
	}
	else {
		/* Set date and time strings to be displayed for current record */
		set_record_timestamp_string(curr, cur_date, cur_time, 32, rectime);
	}

	if (rtype == R_RESTART) {
		/* Don't forget to read the volatile activities structures */
		new_cpu_nr = read_vol_act_structures(ifd, act, file, file_magic,
						     file_hdr.sa_vol_act_nr);

		if (!dp)
			return;

		if (*fmt[f_position]->f_restart) {
			(*fmt[f_position]->f_restart)(&tab, F_MAIN, cur_date, cur_time,
						      !PRINT_LOCAL_TIME(flags) &&
						      !PRINT_TRUE_TIME(flags), &file_hdr,
						      new_cpu_nr);
		}
	}
	else if (rtype == R_COMMENT) {
		char file_comment[MAX_COMMENT_LEN];

		/* Read and replace non printable chars in comment */
		replace_nonprintable_char(ifd, file_comment);

		if (!dp || !DISPLAY_COMMENT(flags))
			return;

		if (*fmt[f_position]->f_comment) {
			(*fmt[f_position]->f_comment)(&tab, F_MAIN, cur_date, cur_time,
						      !PRINT_LOCAL_TIME(flags) &&
						      !PRINT_TRUE_TIME(flags), file_comment,
						      &file_hdr);
		}
	}
}
Ejemplo n.º 2
0
/*
 ***************************************************************************
 * Display COMMENT records for textual (XML-like) reports.
 *
 * IN:
 * @curr		Index in array for current sample statistics.
 * @use_tm_start	Set to TRUE if option -s has been used.
 * @use_tm_end		Set to TRUE if option -e has been used.
 * @tab			Number of tabulations to print.
 * @ifd			Input file descriptor.
 * @rectime		Structure where timestamp (expressed in local time
 *			or in UTC depending on whether option -t has been
 *			used or not) can be saved for current record.
 * @loctime		Structure where timestamp (expressed in local time)
 *			can be saved for current record.
 *
 * OUT:
 * @rectime		Structure where timestamp for current record has
 *			been saved.
 * @loctime		Structure where timestamp for current record has
 *			been saved.
 ***************************************************************************
 */
void write_textual_comments(int curr, int use_tm_start, int use_tm_end, int tab, int ifd,
			    struct tm *rectime, struct tm *loctime)
{
	char cur_date[32], cur_time[32];
	char file_comment[MAX_COMMENT_LEN];

	sa_fread(ifd, file_comment, MAX_COMMENT_LEN, HARD_SIZE);
	file_comment[MAX_COMMENT_LEN - 1] = '\0';

	/* Fill timestamp structure for current record */
	sadf_get_record_timestamp_struct(curr, rectime, loctime);

	/* The record must be in the interval specified by -s/-e options */
	if ((use_tm_start && (datecmp(loctime, &tm_start) < 0)) ||
	    (use_tm_end && (datecmp(loctime, &tm_end) > 0)))
		return;

	set_record_timestamp_string(curr, cur_date, cur_time, 32, rectime);

	if (*fmt[f_position]->f_comment) {
		(*fmt[f_position]->f_comment)(&tab, F_MAIN, cur_date, cur_time,
					      !PRINT_TRUE_TIME(flags), file_comment,
					      &file_hdr);
	}
}
Ejemplo n.º 3
0
/*
 ***************************************************************************
 * Print contents of a special (RESTART or COMMENT) record.
 *
 * IN:
 * @curr		Index in array for current sample statistics.
 * @use_tm_start	Set to TRUE if option -s has been used.
 * @use_tm_end		Set to TRUE if option -e has been used.
 * @rtype		Record type (RESTART or COMMENT).
 * @ifd			Input file descriptor.
 * @rectime		Structure where timestamp (expressed in local time
 *			or in UTC depending on whether option -t has been
 *			used or not) can be saved for current record.
 * @loctime		Structure where timestamp (expressed in local time)
 *			can be saved for current record.
 ***************************************************************************
 */
void sadf_print_special(int curr, int use_tm_start, int use_tm_end, int rtype, int ifd,
			struct tm *rectime, struct tm *loctime)
{
	char cur_date[32], cur_time[32];
	int dp = 1;

	/* Fill timestamp structure (rectime) for current record */
	sadf_get_record_timestamp_struct(curr, rectime, loctime);

	/* Set date and time strings for current record */
	set_record_timestamp_string(curr, cur_date, cur_time, 32, rectime);

	/* The record must be in the interval specified by -s/-e options */
	if ((use_tm_start && (datecmp(loctime, &tm_start) < 0)) ||
	    (use_tm_end && (datecmp(loctime, &tm_end) > 0))) {
		dp = 0;
	}

	if (rtype == R_RESTART) {
		if (!dp)
			return;

		if (*fmt[f_position]->f_restart) {
			(*fmt[f_position]->f_restart)(NULL, F_MAIN, cur_date, cur_time,
						      !PRINT_TRUE_TIME(flags), &file_hdr);
		}
	}
	else if (rtype == R_COMMENT) {
		char file_comment[MAX_COMMENT_LEN];

		sa_fread(ifd, file_comment, MAX_COMMENT_LEN, HARD_SIZE);
		file_comment[MAX_COMMENT_LEN - 1] = '\0';

		if (!dp || !DISPLAY_COMMENT(flags))
			return;

		if (*fmt[f_position]->f_comment) {
			(*fmt[f_position]->f_comment)(NULL, F_MAIN, cur_date, cur_time,
						      !PRINT_TRUE_TIME(flags), file_comment,
						      &file_hdr);
		}
	}
}
Ejemplo n.º 4
0
/*
 ***************************************************************************
 * Display the "timestamp" part of the report (raw format).
 *
 * IN:
 * @parm	Pointer on specific parameters (unused here).
 * @action	Action expected from current function.
 * @cur_date	Date string of current record.
 * @cur_time	Time string of current record.
 * @itv		Interval of time with preceding record (unused here).
 * @file_hdr	System activity file standard header (unused here).
 * @flags	Flags for common options.
 *
 * RETURNS:
 * Pointer on the "timestamp" string.
 ***************************************************************************
 */
__tm_funct_t print_raw_timestamp(void *parm, int action, char *cur_date,
				char *cur_time, unsigned long long itv,
				struct file_header *file_hdr, unsigned int flags)
{
	int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);
	static char pre[80];

	if (action & F_BEGIN) {
		snprintf(pre, 80, "%s%s", cur_time, strlen(cur_date) && utc ? " UTC" : "");
		pre[79] = '\0';
		return pre;
	}

	return NULL;
}
Ejemplo n.º 5
0
/*
 ***************************************************************************
 * Fill rectime structure according to time data saved in current
 * structure.
 *
 * IN:
 * @curr	Index in array for current sample statistics.
 ***************************************************************************
*/
void sar_set_rectime(int curr)
{
	struct tm *ltm;

	/* Check if option -t was specified on the command line */
	if (PRINT_TRUE_TIME(flags)) {
		/* -t */
		rectime.tm_hour = record_hdr[curr].hour;
		rectime.tm_min  = record_hdr[curr].minute;
		rectime.tm_sec  = record_hdr[curr].second;
	}
	else {
		ltm = localtime((const time_t *) &record_hdr[curr].ust_time);
		rectime = *ltm;
	}
}
Ejemplo n.º 6
0
/*
 ***************************************************************************
 * Display the "timestamp" part of the report (XML format).
 *
 * IN:
 * @tab		Number of tabulations.
 * @action	Action expected from current function.
 * @cur_date	Date string of current comment.
 * @cur_time	Time string of current comment.
 * @utc		True if @cur_time is expressed in UTC.
 * @itv		Interval of time with preceding record.
 *
 * OUT:
 * @tab		Number of tabulations.
 ***************************************************************************
 */
__tm_funct_t print_xml_timestamp(int *tab, int action, char *cur_date,
				 char *cur_time, unsigned long long itv,
				 struct file_header *file_hdr, unsigned int flags)
{
	int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);

	if (action & F_BEGIN) {
		xprintf((*tab)++, "<timestamp date=\"%s\" time=\"%s\" utc=\"%d\" interval=\"%llu\">",
			cur_date, cur_time, utc ? 1 : 0, itv);
	}
	if (action & F_END) {
		xprintf(--(*tab), "</timestamp>");
	}

	return NULL;
}
Ejemplo n.º 7
0
/*
 ***************************************************************************
 * Display the "timestamp" part of the report (db format).
 *
 * IN:
 * @parm	Pointer on specific parameters (unused here).
 * @action	Action expected from current function.
 * @cur_date	Date string of current record.
 * @cur_time	Time string of current record.
 * @itv		Interval of time with preceding record.
 * @file_hdr	System activity file standard header.
 * @flags	Flags for common options.
 *
 * RETURNS:
 * Pointer on the "timestamp" string.
 ***************************************************************************
 */
__tm_funct_t print_db_timestamp(void *parm, int action, char *cur_date,
				char *cur_time, unsigned long long itv,
				struct file_header *file_hdr, unsigned int flags)
{
	int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);

	if (action & F_BEGIN) {
		return print_dbppc_timestamp(F_DB_OUTPUT, file_hdr, cur_date, cur_time, utc, itv);
	}
	if (action & F_END) {
		if (DISPLAY_HORIZONTALLY(flags)) {
			printf("\n");
		}
	}

	return NULL;
}
Ejemplo n.º 8
0
/*
 ***************************************************************************
 * Fill the rectime and loctime structures with current record's date and
 * time, based on current record's "number of seconds since the epoch" saved
 * in file.
 * The resulting timestamp is expressed in UTC or in local time, depending
 * on whether option -t has been used or not.
 *
 * IN:
 * @curr	Index in array for current sample statistics.
 * @rectime	Structure where timestamp (expressed in local time or in UTC
 *		depending on whether option -t has been used or not) can be
 *		saved for current record.
 * @loctime	Structure where timestamp (expressed in local time) can be
 *		saved for current record.
 *
 * OUT:
 * @rectime	Structure where timestamp for current record has been saved.
 * @loctime	Structure where timestamp for current record has been saved.
 ***************************************************************************
*/
void sadf_get_record_timestamp_struct(int curr, struct tm *rectime, struct tm *loctime)
{
	struct tm *ltm;

	if ((ltm = localtime((const time_t *) &record_hdr[curr].ust_time)) != NULL) {
		*loctime = *ltm;
	}

	if (!PRINT_TRUE_TIME(flags)) {
		/* Option -t not used: Display timestamp in UTC */
		ltm = gmtime((const time_t *) &record_hdr[curr].ust_time);
	}

	if (ltm) {
		*rectime = *ltm;
	}
}
Ejemplo n.º 9
0
/*
 ***************************************************************************
 * Display restart records for textual (XML-like) reports.
 *
 * IN:
 * @curr		Index in array for current sample statistics.
 * @use_tm_start	Set to TRUE if option -s has been used.
 * @use_tm_end		Set to TRUE if option -e has been used.
 * @tab			Number of tabulations to print.
 * @rectime		Structure where timestamp (expressed in local time
 *			or in UTC depending on whether option -t has been
 *			used or not) can be saved for current record.
 * @loctime		Structure where timestamp (expressed in local time)
 *			can be saved for current record.
 *
 * OUT:
 * @rectime		Structure where timestamp for current record has
 *			been saved.
 * @loctime		Structure where timestamp for current record has
 *			been saved.
 ***************************************************************************
 */
void write_textual_restarts(int curr, int use_tm_start, int use_tm_end, int tab,
			    struct tm *rectime, struct tm *loctime)
{
	char cur_date[32], cur_time[32];

	/* Fill timestamp structure for current record */
	sadf_get_record_timestamp_struct(curr, rectime, loctime);

	/* The record must be in the interval specified by -s/-e options */
	if ((use_tm_start && (datecmp(loctime, &tm_start) < 0)) ||
	    (use_tm_end && (datecmp(loctime, &tm_end) > 0)))
		return;

	set_record_timestamp_string(curr, cur_date, cur_time, 32, rectime);

	if (*fmt[f_position]->f_restart) {
		(*fmt[f_position]->f_restart)(&tab, F_MAIN, cur_date, cur_time,
					      !PRINT_TRUE_TIME(flags), &file_hdr);
	}
}
Ejemplo n.º 10
0
/*
 ***************************************************************************
 * write_mech_stats() -
 * Replace the old write_stats_for_ppc() and write_stats_for_db(),
 * making it easier for them to remain in sync and print the same data.
 *
 * IN:
 * @curr	Index in array for current sample statistics.
 * @dt		Interval of time in seconds.
 * @itv		Interval of time in jiffies.
 * @g_itv	Interval of time in jiffies multiplied by the number of
 * 		processors.
 * @cur_date	Date string for current record.
 * @cur_time	Time string for current record.
 * @act_id	Activity to display, or ~0 for all.
 ***************************************************************************
 */
void write_mech_stats(int curr, unsigned long dt, unsigned long long itv,
		      unsigned long long g_itv, char *cur_date, char *cur_time,
		      unsigned int act_id)
{
	int i;
	char pre[80], temp[80];	/* Text at beginning of each line */
	int isdb = (format == F_DB_OUTPUT);

	/* This substring appears on every output line, preformat it here */
	snprintf(pre, 80, "%s%s%ld%s",
		 file_hdr.sa_nodename, seps[isdb], dt, seps[isdb]);
	if (strlen(cur_date)) {
		snprintf(temp, 80, "%s%s ", pre, cur_date);
	}
	else {
		strcpy(temp, pre);
	}
	snprintf(pre, 80, "%s%s%s", temp, cur_time,
		 strlen(cur_date) && !PRINT_LOCAL_TIME(flags) &&
		 !PRINT_TRUE_TIME(flags) ? " UTC" : "");
	pre[79] = '\0';

	if (DISPLAY_HORIZONTALLY(flags)) {
		printf("%s", pre);
	}

	for (i = 0; i < NR_ACT; i++) {

		if ((act_id != ALL_ACTIVITIES) && (act[i]->id != act_id))
			continue;

		if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) {
			(*act[i]->f_render)(act[i], isdb, pre, curr,
					    NEED_GLOBAL_ITV(act[i]->options) ? g_itv : itv);
		}
	}

	if (DISPLAY_HORIZONTALLY(flags)) {
		printf("\n");
	}
}
Ejemplo n.º 11
0
/*
 ***************************************************************************
 * Display the "timestamp" part of the report (JSON format).
 *
 * IN:
 * @tab		Number of tabulations.
 * @action	Action expected from current function.
 * @cur_date	Date string of current comment.
 * @cur_time	Time string of current comment.
 * @utc		True if @cur_time is expressed in UTC.
 * @itv		Interval of time with preceding record.
 *
 * OUT:
 * @tab		Number of tabulations.
 ***************************************************************************
 */
__tm_funct_t print_json_timestamp(int *tab, int action, char *cur_date,
				  char *cur_time, unsigned long long itv,
				  struct file_header *file_hdr, unsigned int flags)
{
	int utc = !PRINT_LOCAL_TIME(flags) && !PRINT_TRUE_TIME(flags);

	if (action & F_BEGIN) {
		xprintf0(*tab,
			 "\"timestamp\": {\"date\": \"%s\", \"time\": \"%s\", "
			 "\"utc\": %d, \"interval\": %llu}",
			 cur_date, cur_time, utc ? 1 : 0, itv);
	}
	if (action & F_MAIN) {
		printf(",\n");
	}
	if (action & F_END) {
		printf("\n");
	}

	return NULL;
}
Ejemplo n.º 12
0
/*
 ***************************************************************************
 * Fill the (struct tm) rectime structure with current record's time,
 * based on current record's time data saved in file.
 * The resulting timestamp is expressed in the locale of the file creator
 * or in the user's own locale depending on whether option -t has been used
 * or not.
 *
 * IN:
 * @curr	Index in array for current sample statistics.
 *
 * RETURNS:
 * 1 if an error was detected, or 0 otherwise.
 ***************************************************************************
*/
int sar_get_record_timestamp_struct(int curr)
{
	struct tm *ltm;

	/* Check if option -t was specified on the command line */
	if (PRINT_TRUE_TIME(flags)) {
		/* -t */
		rectime.tm_hour = record_hdr[curr].hour;
		rectime.tm_min  = record_hdr[curr].minute;
		rectime.tm_sec  = record_hdr[curr].second;
	}
	else {
		if ((ltm = localtime((const time_t *) &record_hdr[curr].ust_time)) == NULL)
			/*
			 * An error was detected.
			 * The rectime structure has NOT been updated.
			 */
			return 1;

		rectime = *ltm;
	}

	return 0;
}
Ejemplo n.º 13
0
/*
 ***************************************************************************
 * Display activity records for textual (XML-like) formats.
 *
 * IN:
 * @curr		Index in array for current sample statistics.
 * @use_tm_start	Set to TRUE if option -s has been used.
 * @use_tm_end		Set to TRUE if option -e has been used.
 * @reset		Set to TRUE if last_uptime should be reinitialized
 *			(used in next_slice() function).
 * @tab			Number of tabulations to print.
 * @cpu_nr		Number of processors.
 * @rectime		Structure where timestamp (expressed in local time
 *			or in UTC depending on whether option -t has been
 *			used or not) can be saved for current record.
 * @loctime		Structure where timestamp (expressed in local time)
 *			can be saved for current record.
 *
 * OUT:
 * @cnt			Set to 0 to indicate that no other lines of stats
 * 			should be displayed.
 *
 * RETURNS:
 * 1 if stats have been successfully displayed.
 ***************************************************************************
 */
int write_textual_stats(int curr, int use_tm_start, int use_tm_end, int reset,
			long *cnt, int tab, __nr_t cpu_nr, struct tm *rectime,
			struct tm *loctime)
{
	int i;
	unsigned long long dt, itv, g_itv;
	char cur_date[32], cur_time[32];
	static int cross_day = FALSE;

	/* Fill timestamp structure (rectime) for current record */
	sadf_get_record_timestamp_struct(curr, rectime, loctime);

	/*
	 * Check time (1).
	 * For this first check, we use the time interval entered on
	 * the command line. This is equivalent to sar's option -i which
	 * selects records at seconds as close as possible to the number
	 * specified by the interval parameter.
	 */
	if (!next_slice(record_hdr[2].uptime0, record_hdr[curr].uptime0,
			reset, interval))
		/* Not close enough to desired interval */
		return 0;

	/* Check if we are beginning a new day */
	if (use_tm_start && record_hdr[!curr].ust_time &&
	    (record_hdr[curr].ust_time > record_hdr[!curr].ust_time) &&
	    (record_hdr[curr].hour < record_hdr[!curr].hour)) {
		cross_day = TRUE;
	}

	if (cross_day) {
		/*
		 * This is necessary if we want to properly handle something like:
		 * sar -s time_start -e time_end with
		 * time_start(day D) > time_end(day D+1)
		 */
		loctime->tm_hour += 24;
	}

	/* Check time (2) */
	if (use_tm_start && (datecmp(loctime, &tm_start) < 0))
		/* it's too soon... */
		return 0;

	/* Get interval values */
	get_itv_value(&record_hdr[curr], &record_hdr[!curr],
		      cpu_nr, &itv, &g_itv);

	/* Check time (3) */
	if (use_tm_end && (datecmp(loctime, &tm_end) > 0)) {
		/* It's too late... */
		*cnt = 0;
		return 0;
	}

	dt = itv / HZ;
	/* Correct rounding error for dt */
	if ((itv % HZ) >= (HZ / 2)) {
		dt++;
	}

	/* Set date and time strings for current record */
	set_record_timestamp_string(curr, cur_date, cur_time, 32, rectime);

	if (*fmt[f_position]->f_timestamp) {
		(*fmt[f_position]->f_timestamp)(&tab, F_BEGIN, cur_date, cur_time,
						!PRINT_TRUE_TIME(flags), dt);
	}
	if (format == F_XML_OUTPUT) {
		tab++;
	}

	/* Display textual statistics */
	for (i = 0; i < NR_ACT; i++) {

		/* This code is not generic at all...! */
		if (format == F_JSON_OUTPUT) {
			/* JSON output */
			if (CLOSE_MARKUP(act[i]->options) ||
			    (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) {
				
				if (IS_SELECTED(act[i]->options) && (act[i]->nr > 0)) {
					printf(",");

					if (*fmt[f_position]->f_timestamp) {
						(*fmt[f_position]->f_timestamp)(&tab, F_MAIN, cur_date, cur_time,
										!PRINT_TRUE_TIME(flags), dt);
					}
				}
				(*act[i]->f_json_print)(act[i], curr, tab, NEED_GLOBAL_ITV(act[i]->options) ?
							g_itv : itv);
			}
		}
		else {
			/* XML output */
			if (CLOSE_MARKUP(act[i]->options) ||
			    (IS_SELECTED(act[i]->options) && (act[i]->nr > 0))) {
				(*act[i]->f_xml_print)(act[i], curr, tab, NEED_GLOBAL_ITV(act[i]->options) ?
						       g_itv : itv);
			}
		}
	}

	if (*fmt[f_position]->f_timestamp) {
		(*fmt[f_position]->f_timestamp)(&tab, F_END, cur_date, cur_time,
						!PRINT_TRUE_TIME(flags), dt);
	}

	return 1;
}
Ejemplo n.º 14
0
/*
 ***************************************************************************
 * Main entry to the sadf program
 ***************************************************************************
 */
int main(int argc, char **argv)
{
	int opt = 1, sar_options = 0;
	int day_offset = 0;
	int i, rc;
	char dfile[MAX_FILE_LEN];
	char *t;

	/* Get HZ */
	get_HZ();

	/* Compute page shift in kB */
	get_kb_shift();

	dfile[0] = '\0';

#ifdef USE_NLS
	/* Init National Language Support */
	init_nls();
#endif

	tm_start.use = tm_end.use = FALSE;

	/* Allocate and init activity bitmaps */
	allocate_bitmaps(act);

	/* Init some structures */
	init_structures();

	/* Process options */
	while (opt < argc) {

		if (!strcmp(argv[opt], "-I")) {
			if (argv[++opt] && sar_options) {
				if (parse_sar_I_opt(argv, &opt, act)) {
					usage(argv[0]);
				}
			}
			else {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-P")) {
			if (parse_sa_P_opt(argv, &opt, &flags, act)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-s")) {
			/* Get time start */
			if (parse_timestamp(argv, &opt, &tm_start, DEF_TMSTART)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-e")) {
			/* Get time end */
			if (parse_timestamp(argv, &opt, &tm_end, DEF_TMEND)) {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-O")) {
			/* Parse SVG options */
			if (!argv[++opt] || sar_options) {
				usage(argv[0]);
			}
			for (t = strtok(argv[opt], ","); t; t = strtok(NULL, ",")) {
				if (!strcmp(t, K_SKIP_EMPTY)) {
					flags |= S_F_SVG_SKIP;
				}
				else if (!strcmp(t, K_AUTOSCALE)) {
					flags |= S_F_SVG_AUTOSCALE;
				}
				else {
					usage(argv[0]);
				}
			}
			opt++;
		}

		else if ((strlen(argv[opt]) > 1) &&
			 (strlen(argv[opt]) < 4) &&
			 !strncmp(argv[opt], "-", 1) &&
			 (strspn(argv[opt] + 1, DIGITS) == (strlen(argv[opt]) - 1))) {
			if (dfile[0] || day_offset) {
				/* File already specified */
				usage(argv[0]);
			}
			day_offset = atoi(argv[opt++] + 1);
		}

		else if (!strcmp(argv[opt], "--")) {
			sar_options = 1;
			opt++;
		}

		else if (!strcmp(argv[opt], "-m")) {
			if (argv[++opt] && sar_options) {
				/* Parse sar's option -m */
				if (parse_sar_m_opt(argv, &opt, act)) {
					usage(argv[0]);
				}
			}
			else {
				usage(argv[0]);
			}
		}

		else if (!strcmp(argv[opt], "-n")) {
			if (argv[++opt] && sar_options) {
				/* Parse sar's option -n */
				if (parse_sar_n_opt(argv, &opt, act)) {
					usage(argv[0]);
				}
			}
			else {
				usage(argv[0]);
			}
		}

		else if (!strncmp(argv[opt], "-", 1)) {
			/* Other options not previously tested */
			if (sar_options) {
				if ((rc = parse_sar_opt(argv, &opt, act, &flags, C_SADF)) != 0) {
					if (rc == 1) {
						usage(argv[0]);
					}
					exit(1);
				}
			}
			else {

				for (i = 1; *(argv[opt] + i); i++) {

					switch (*(argv[opt] + i)) {

					case 'C':
						flags |= S_F_COMMENT;
						break;

					case 'c':
						if (format) {
							usage(argv[0]);
						}
						format = F_CONV_OUTPUT;
						break;

					case 'd':
						if (format) {
							usage(argv[0]);
						}
						format = F_DB_OUTPUT;
						break;

					case 'g':
						if (format) {
							usage(argv[0]);
						}
						format = F_SVG_OUTPUT;
						break;

					case 'h':
						flags |= S_F_HORIZONTALLY;
						break;

					case 'H':
						flags |= S_F_HDR_ONLY;
						break;

					case 'j':
						if (format) {
							usage(argv[0]);
						}
						format = F_JSON_OUTPUT;
						break;

					case 'p':
						if (format) {
							usage(argv[0]);
						}
						format = F_PPC_OUTPUT;
						break;

					case 'T':
						flags |= S_F_LOCAL_TIME;
						break;

					case 't':
						flags |= S_F_TRUE_TIME;
						break;

					case 'U':
						flags |= S_F_SEC_EPOCH;
						break;

					case 'x':
						if (format) {
							usage(argv[0]);
						}
						format = F_XML_OUTPUT;
						break;

					case 'V':
						print_version();
						break;

					default:
						usage(argv[0]);
					}
				}
			}
			opt++;
		}

		/* Get data file name */
		else if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
			if (dfile[0] || day_offset) {
				/* File already specified */
				usage(argv[0]);
			}
			if (!strcmp(argv[opt], "-")) {
				/* File name set to '-' */
				set_default_file(dfile, 0, -1);
				opt++;
			}
			else if (!strncmp(argv[opt], "-", 1)) {
				/* Bad option */
				usage(argv[0]);
			}
			else {
				/* Write data to file */
				strncpy(dfile, argv[opt++], MAX_FILE_LEN);
				dfile[MAX_FILE_LEN - 1] = '\0';
				/* Check if this is an alternate directory for sa files */
				check_alt_sa_dir(dfile, 0, -1);
			}
		}

		else if (interval < 0) {
			/* Get interval */
			if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
				usage(argv[0]);
			}
			interval = atol(argv[opt++]);
			if (interval <= 0) {
				usage(argv[0]);
			}
		}

		else {
			/* Get count value */
			if (strspn(argv[opt], DIGITS) != strlen(argv[opt])) {
				usage(argv[0]);
			}
			if (count) {
				/* Count parameter already set */
				usage(argv[0]);
			}
			count = atol(argv[opt++]);
			if (count < 0) {
				usage(argv[0]);
			}
			else if (!count) {
				count = -1;	/* To generate a report continuously */
			}
		}
	}

	/* sadf reads current daily data file by default */
	if (!dfile[0]) {
		set_default_file(dfile, day_offset, -1);
	}

	if (tm_start.use && tm_end.use && (tm_end.tm_hour < tm_start.tm_hour)) {
		tm_end.tm_hour += 24;
	}

	if (USE_PRETTY_OPTION(flags)) {
		dm_major = get_devmap_major();
	}

	/* Options -T, -t and -U are mutually exclusive */
	if ((PRINT_LOCAL_TIME(flags) + PRINT_TRUE_TIME(flags) +
	    PRINT_SEC_EPOCH(flags)) > 1) {
		usage(argv[0]);
	}

	/*
	 * Display all the contents of the daily data file if the count parameter
	 * was not set on the command line.
	 */
	if (!count) {
		count = -1;
	}

	/* Default is CPU activity */
	select_default_activity(act);

	/* Check options consistency with selected output format. Default is PPC display */
	check_format_options();

	if (interval < 0) {
		interval = 1;
	}

	if (format == F_CONV_OUTPUT) {
		/* Convert file to current format */
		convert_file(dfile, act);
	}
	else {
		/* Read stats from file */
		read_stats_from_file(dfile);
	}

	/* Free bitmaps */
	free_bitmaps(act);

	return 0;
}