2 * sar, sadc, sadf, mpstat and iostat common routines.
3 * (C) 1999-2016 by Sebastien GODARD (sysstat <at> orange.fr)
5 ***************************************************************************
6 * This program is free software; you can redistribute it and/or modify it *
7 * under the terms of the GNU General Public License as published by the *
8 * Free Software Foundation; either version 2 of the License, or (at your *
9 * option) any later version. *
11 * This program is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without the implied warranty of MERCHANTABILITY *
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
16 * You should have received a copy of the GNU General Public License along *
17 * with this program; if not, write to the Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *
19 ***************************************************************************
29 #include <unistd.h> /* For STDOUT_FILENO, among others */
30 #include <sys/ioctl.h>
31 #include <sys/types.h>
44 #define _(string) gettext(string)
46 #define _(string) (string)
49 /* Number of ticks per second */
51 /* Number of bit shifts to convert pages to kB */
52 unsigned int kb_shift;
55 char sc_percent_high[MAX_SGR_LEN] = C_BOLD_RED;
56 char sc_percent_low[MAX_SGR_LEN] = C_BOLD_BLUE;
57 char sc_zero_int_stat[MAX_SGR_LEN] = C_LIGHT_YELLOW;
58 char sc_int_stat[MAX_SGR_LEN] = C_BOLD_YELLOW;
59 char sc_item_name[MAX_SGR_LEN] = C_LIGHT_GREEN;
60 char sc_sa_restart[MAX_SGR_LEN] = C_LIGHT_RED;
61 char sc_sa_comment[MAX_SGR_LEN] = C_LIGHT_CYAN;
62 char sc_normal[MAX_SGR_LEN] = C_NORMAL;
64 /* Type of persistent device names used in sar and iostat */
65 char persistent_name_type[MAX_FILE_LEN];
68 ***************************************************************************
69 * Print sysstat version number and exit.
70 ***************************************************************************
72 void print_version(void)
74 printf(_("sysstat version %s\n"), VERSION);
75 printf("(C) Sebastien Godard (sysstat <at> orange.fr)\n");
80 ***************************************************************************
81 * Get local date and time.
84 * @d_off Day offset (number of days to go back in the past).
87 * @rectime Current local date and time.
90 * Value of time in seconds since the Epoch.
91 ***************************************************************************
93 time_t get_localtime(struct tm *rectime, int d_off)
99 timer -= SEC_PER_DAY * d_off;
100 ltm = localtime(&timer);
109 ***************************************************************************
110 * Get date and time expressed in UTC.
113 * @d_off Day offset (number of days to go back in the past).
116 * @rectime Current date and time expressed in UTC.
119 * Value of time in seconds since the Epoch.
120 ***************************************************************************
122 time_t get_gmtime(struct tm *rectime, int d_off)
128 timer -= SEC_PER_DAY * d_off;
129 ltm = gmtime(&timer);
138 ***************************************************************************
139 * Get date and time and take into account <ENV_TIME_DEFTM> variable.
142 * @d_off Day offset (number of days to go back in the past).
145 * @rectime Current date and time.
148 * Value of time in seconds since the Epoch.
149 ***************************************************************************
151 time_t get_time(struct tm *rectime, int d_off)
157 /* Read environment variable value once */
158 if ((e = getenv(ENV_TIME_DEFTM)) != NULL) {
159 utc = !strcmp(e, K_UTC);
165 return get_gmtime(rectime, d_off);
167 return get_localtime(rectime, d_off);
171 ***************************************************************************
172 * Count number of comma-separated values in arguments list. For example,
173 * the number will be 3 for the list "foobar -p 1 -p 2,3,4 2 5".
176 * @arg_c Number of arguments in the list.
177 * @arg_v Arguments list.
180 * Number of comma-separated values in the list.
181 ***************************************************************************
183 int count_csvalues(int arg_c, char **arg_v)
189 while (opt < arg_c) {
190 if (strchr(arg_v[opt], ',')) {
191 for (t = arg_v[opt]; t; t = strchr(t + 1, ',')) {
202 ***************************************************************************
203 * Look for partitions of a given block device in /sys filesystem.
206 * @dev_name Name of the block device.
209 * Number of partitions for the given block device.
210 ***************************************************************************
212 int get_dev_part_nr(char *dev_name)
216 char dfile[MAX_PF_NAME], line[MAX_PF_NAME];
219 snprintf(dfile, MAX_PF_NAME, "%s/%s", SYSFS_BLOCK, dev_name);
220 dfile[MAX_PF_NAME - 1] = '\0';
222 /* Open current device directory in /sys/block */
223 if ((dir = opendir(dfile)) == NULL)
226 /* Get current file entry */
227 while ((drd = readdir(dir)) != NULL) {
228 if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
230 snprintf(line, MAX_PF_NAME, "%s/%s/%s", dfile, drd->d_name, S_STAT);
231 line[MAX_PF_NAME - 1] = '\0';
233 /* Try to guess if current entry is a directory containing a stat file */
234 if (!access(line, R_OK)) {
240 /* Close directory */
247 ***************************************************************************
248 * Look for block devices present in /sys/ filesystem:
249 * Check first that sysfs is mounted (done by trying to open /sys/block
250 * directory), then find number of devices registered.
253 * @display_partitions Set to TRUE if partitions must also be counted.
256 * Total number of block devices (and partitions if @display_partitions was
258 ***************************************************************************
260 int get_sysfs_dev_nr(int display_partitions)
264 char line[MAX_PF_NAME];
267 /* Open /sys/block directory */
268 if ((dir = opendir(SYSFS_BLOCK)) == NULL)
269 /* sysfs not mounted, or perhaps this is an old kernel */
272 /* Get current file entry in /sys/block directory */
273 while ((drd = readdir(dir)) != NULL) {
274 if (!strcmp(drd->d_name, ".") || !strcmp(drd->d_name, ".."))
276 snprintf(line, MAX_PF_NAME, "%s/%s/%s", SYSFS_BLOCK, drd->d_name, S_STAT);
277 line[MAX_PF_NAME - 1] = '\0';
279 /* Try to guess if current entry is a directory containing a stat file */
280 if (!access(line, R_OK)) {
284 if (display_partitions) {
285 /* We also want the number of partitions for this device */
286 dev += get_dev_part_nr(drd->d_name);
291 /* Close /sys/block directory */
298 ***************************************************************************
299 * Read /proc/devices file and get device-mapper major number.
300 * If device-mapper entry is not found in file, assume it's not active.
303 * Device-mapper major number.
304 ***************************************************************************
306 unsigned int get_devmap_major(void)
311 * Linux uses 12 bits for the major number,
312 * so this shouldn't match any real device.
314 unsigned int dm_major = ~0U;
316 if ((fp = fopen(DEVICES, "r")) == NULL)
319 while (fgets(line, sizeof(line), fp) != NULL) {
321 if (strstr(line, "device-mapper")) {
322 /* Read device-mapper major number */
323 sscanf(line, "%u", &dm_major);
333 ***************************************************************************
334 * Returns whether S_TIME_FORMAT is set to ISO.
337 * TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
338 ***************************************************************************
340 int is_iso_time_fmt(void)
342 static int is_iso = -1;
346 is_iso = (((e = getenv(ENV_TIME_FMT)) != NULL) && !strcmp(e, K_ISO));
352 ***************************************************************************
356 * @rectime Date to display (don't use time fields).
357 * @sysname System name to display.
358 * @release System release number to display.
359 * @nodename Hostname to display.
360 * @machine Machine architecture to display.
361 * @cpu_nr Number of CPU.
364 * TRUE if S_TIME_FORMAT is set to ISO, or FALSE otherwise.
365 ***************************************************************************
367 int print_gal_header(struct tm *rectime, char *sysname, char *release,
368 char *nodename, char *machine, int cpu_nr)
373 if (rectime == NULL) {
374 strcpy(cur_date, "?/?/?");
376 else if (is_iso_time_fmt()) {
377 strftime(cur_date, sizeof(cur_date), "%Y-%m-%d", rectime);
381 strftime(cur_date, sizeof(cur_date), "%x", rectime);
384 printf("%s %s (%s) \t%s \t_%s_\t(%d CPU)\n", sysname, release, nodename,
385 cur_date, machine, cpu_nr);
392 ***************************************************************************
393 * Init National Language Support.
394 ***************************************************************************
398 setlocale(LC_MESSAGES, "");
399 setlocale(LC_CTYPE, "");
400 setlocale(LC_TIME, "");
401 setlocale(LC_NUMERIC, "");
403 bindtextdomain(PACKAGE, LOCALEDIR);
409 ***************************************************************************
410 * Get number of rows for current window.
414 ***************************************************************************
416 int get_win_height(void)
420 * This default value will be used whenever STDOUT
421 * is redirected to a pipe or a file
423 int rows = 3600 * 24;
425 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &win) != -1) {
426 if (win.ws_row > 2) {
427 rows = win.ws_row - 2;
434 ***************************************************************************
435 * Canonicalize and remove /dev from path name.
438 * @name Device name (may begin with "/dev/" or can be a symlink).
442 ***************************************************************************
444 char *device_name(char *name)
446 static char out[MAX_FILE_LEN];
450 /* realpath() creates new string, so we need to free it later */
451 resolved_name = realpath(name, NULL);
453 /* If path doesn't exist, just return input */
454 if (!resolved_name) {
458 if (!strncmp(resolved_name, "/dev/", 5)) {
461 strncpy(out, resolved_name + i, MAX_FILE_LEN);
462 out[MAX_FILE_LEN - 1] = '\0';
470 ***************************************************************************
471 * Test whether given name is a device or a partition, using sysfs.
472 * This is more straightforward that using ioc_iswhole() function from
473 * ioconf.c which should be used only with kernels that don't have sysfs.
476 * @name Device or partition name.
477 * @allow_virtual TRUE if virtual devices are also accepted.
478 * The device is assumed to be virtual if no
479 * /sys/block/<device>/device link exists.
482 * TRUE if @name is not a partition.
483 ***************************************************************************
485 int is_device(char *name, int allow_virtual)
487 char syspath[PATH_MAX];
490 /* Some devices may have a slash in their name (eg. cciss/c0d0...) */
491 while ((slash = strchr(name, '/'))) {
494 snprintf(syspath, sizeof(syspath), "%s/%s%s", SYSFS_BLOCK, name,
495 allow_virtual ? "" : "/device");
497 return !(access(syspath, F_OK));
501 ***************************************************************************
502 * Get page shift in kB.
503 ***************************************************************************
505 void get_kb_shift(void)
510 /* One can also use getpagesize() to get the size of a page */
511 if ((size = sysconf(_SC_PAGESIZE)) == -1) {
515 size >>= 10; /* Assume that a page has a minimum size of 1 kB */
522 kb_shift = (unsigned int) shift;
526 ***************************************************************************
527 * Get number of clock ticks per second.
528 ***************************************************************************
534 if ((ticks = sysconf(_SC_CLK_TCK)) == -1) {
538 hz = (unsigned int) ticks;
542 ***************************************************************************
543 * Workaround for CPU counters read from /proc/stat: Dyn-tick kernels
544 * have a race issue that can make those counters go backward.
545 ***************************************************************************
547 double ll_sp_value(unsigned long long value1, unsigned long long value2,
548 unsigned long long itv)
553 return SP_VALUE(value1, value2, itv);
557 ***************************************************************************
558 * Compute time interval.
561 * @prev_uptime Previous uptime value in jiffies.
562 * @curr_uptime Current uptime value in jiffies.
565 * Interval of time in jiffies.
566 ***************************************************************************
568 unsigned long long get_interval(unsigned long long prev_uptime,
569 unsigned long long curr_uptime)
571 unsigned long long itv;
573 /* prev_time=0 when displaying stats since system startup */
574 itv = curr_uptime - prev_uptime;
576 if (!itv) { /* Paranoia checking */
584 ***************************************************************************
585 * Since ticks may vary slightly from CPU to CPU, we'll want
586 * to recalculate itv based on this CPU's tick count, rather
587 * than that reported by the "cpu" line. Otherwise we
588 * occasionally end up with slightly skewed figures, with
589 * the skew being greater as the time interval grows shorter.
592 * @scc Current sample statistics for current CPU.
593 * @scp Previous sample statistics for current CPU.
596 * Interval of time based on current CPU.
597 ***************************************************************************
599 unsigned long long get_per_cpu_interval(struct stats_cpu *scc,
600 struct stats_cpu *scp)
602 unsigned long long ishift = 0LL;
604 if ((scc->cpu_user - scc->cpu_guest) < (scp->cpu_user - scp->cpu_guest)) {
606 * Sometimes the nr of jiffies spent in guest mode given by the guest
607 * counter in /proc/stat is slightly higher than that included in
608 * the user counter. Update the interval value accordingly.
610 ishift += (scp->cpu_user - scp->cpu_guest) -
611 (scc->cpu_user - scc->cpu_guest);
613 if ((scc->cpu_nice - scc->cpu_guest_nice) < (scp->cpu_nice - scp->cpu_guest_nice)) {
615 * Idem for nr of jiffies spent in guest_nice mode.
617 ishift += (scp->cpu_nice - scp->cpu_guest_nice) -
618 (scc->cpu_nice - scc->cpu_guest_nice);
622 * Don't take cpu_guest and cpu_guest_nice into account
623 * because cpu_user and cpu_nice already include them.
625 return ((scc->cpu_user + scc->cpu_nice +
626 scc->cpu_sys + scc->cpu_iowait +
627 scc->cpu_idle + scc->cpu_steal +
628 scc->cpu_hardirq + scc->cpu_softirq) -
629 (scp->cpu_user + scp->cpu_nice +
630 scp->cpu_sys + scp->cpu_iowait +
631 scp->cpu_idle + scp->cpu_steal +
632 scp->cpu_hardirq + scp->cpu_softirq) +
637 ***************************************************************************
638 * Unhandled situation: Panic and exit. Should never happen.
641 * @function Function name where situation occured.
642 * @error_code Error code.
643 ***************************************************************************
645 void sysstat_panic(const char *function, int error_code)
647 fprintf(stderr, "sysstat: %s[%d]: Internal error...\n",
648 function, error_code);
653 ***************************************************************************
654 * Count number of bits set in an array.
657 * @ptr Pointer to array.
658 * @size Size of array in bytes.
661 * Number of bits set in the array.
662 ***************************************************************************
664 int count_bits(void *ptr, int size)
670 for (i = 0; i < size; i++, p++) {
683 ***************************************************************************
684 * Compute "extended" device statistics (service time, etc.).
687 * @sdc Structure with current device statistics.
688 * @sdp Structure with previous device statistics.
689 * @itv Interval of time in jiffies.
692 * @xds Structure with extended statistics.
693 ***************************************************************************
695 void compute_ext_disk_stats(struct stats_disk *sdc, struct stats_disk *sdp,
696 unsigned long long itv, struct ext_disk_stats *xds)
699 = ((double) (sdc->nr_ios - sdp->nr_ios)) * HZ / itv;
701 xds->util = S_VALUE(sdp->tot_ticks, sdc->tot_ticks, itv);
702 xds->svctm = tput ? xds->util / tput : 0.0;
704 * Kernel gives ticks already in milliseconds for all platforms
705 * => no need for further scaling.
707 xds->await = (sdc->nr_ios - sdp->nr_ios) ?
708 ((sdc->rd_ticks - sdp->rd_ticks) + (sdc->wr_ticks - sdp->wr_ticks)) /
709 ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
710 xds->arqsz = (sdc->nr_ios - sdp->nr_ios) ?
711 ((sdc->rd_sect - sdp->rd_sect) + (sdc->wr_sect - sdp->wr_sect)) /
712 ((double) (sdc->nr_ios - sdp->nr_ios)) : 0.0;
716 ***************************************************************************
717 * Convert in-place input string to lowercase.
720 * @str String to be converted.
723 * @str String in lowercase.
726 * String in lowercase.
727 ***************************************************************************
729 char *strtolower(char *str)
742 ***************************************************************************
743 * Get persistent type name directory from type.
746 * @type Persistent type name (UUID, LABEL, etc.)
749 * Path to the persistent type name directory, or NULL if access is denied.
750 ***************************************************************************
752 char *get_persistent_type_dir(char *type)
756 snprintf(dir, 32, "%s-%s", DEV_DISK_BY, type);
758 if (access(dir, R_OK)) {
766 ***************************************************************************
767 * Get persistent name absolute path.
770 * @name Persistent name.
773 * Path to the persistent name, or NULL if file doesn't exist.
774 ***************************************************************************
776 char *get_persistent_name_path(char *name)
778 static char path[PATH_MAX];
780 snprintf(path, PATH_MAX, "%s/%s",
781 get_persistent_type_dir(persistent_name_type), name);
783 if (access(path, F_OK)) {
791 ***************************************************************************
792 * Get files from persistent type name directory.
795 * List of files in the persistent type name directory in alphabetical order.
796 ***************************************************************************
798 char **get_persistent_names(void)
803 struct dirent **namelist;
805 /* Get directory name for selected persistent type */
806 dir = get_persistent_type_dir(persistent_name_type);
810 n = scandir(dir, &namelist, NULL, alphasort);
814 /* If directory is empty, it contains 2 entries: "." and ".." */
816 /* Free list and return NULL */
819 /* Ignore the "." and "..", but keep place for one last NULL. */
820 files = (char **) calloc(n - 1, sizeof(char *));
825 * i is for traversing namelist, k is for files.
826 * i != k because we are ignoring "." and ".." entries.
828 for (i = 0; i < n; i++) {
829 /* Ignore "." and "..". */
830 if (!strcmp(".", namelist[i]->d_name) ||
831 !strcmp("..", namelist[i]->d_name))
834 files[k] = (char *) calloc(strlen(namelist[i]->d_name) + 1, sizeof(char));
838 strcpy(files[k++], namelist[i]->d_name);
844 for (i = 0; i < n; i++) {
853 ***************************************************************************
854 * Get persistent name from pretty name.
857 * @pretty Pretty name (e.g. sda, sda1, ..).
861 ***************************************************************************
863 char *get_persistent_name_from_pretty(char *pretty)
868 char **persist_names;
869 char target[PATH_MAX];
870 static char persist_name[FILENAME_MAX];
872 persist_name[0] = '\0';
874 /* Get list of files from persistent type name directory */
875 persist_names = get_persistent_names();
879 while (persist_names[++i]) {
880 /* Get absolute path for current persistent name */
881 link = get_persistent_name_path(persist_names[i]);
885 /* Persistent name is usually a symlink: Read it... */
886 r = readlink(link, target, PATH_MAX);
887 if ((r <= 0) || (r >= PATH_MAX))
892 /* ... and get device pretty name it points at */
893 name = basename(target);
894 if (!name || (name[0] == '\0'))
897 if (!strncmp(name, pretty, FILENAME_MAX)) {
898 /* We have found pretty name for current persistent one */
899 strncpy(persist_name, persist_names[i], FILENAME_MAX);
900 persist_name[FILENAME_MAX - 1] = '\0';
906 while (persist_names[++i]) {
907 free (persist_names[i]);
909 free (persist_names);
911 if (strlen(persist_name) <= 0)
918 ***************************************************************************
919 * Get pretty name (sda, sda1...) from persistent name.
922 * @persistent Persistent name.
926 ***************************************************************************
928 char *get_pretty_name_from_persistent(char *persistent)
931 char *link, *pretty, target[PATH_MAX];
933 /* Get absolute path for persistent name */
934 link = get_persistent_name_path(persistent);
938 /* Persistent name is usually a symlink: Read it... */
939 r = readlink(link, target, PATH_MAX);
940 if ((r <= 0) || (r >= PATH_MAX))
945 /* ... and get device pretty name it points at */
946 pretty = basename(target);
947 if (!pretty || (pretty[0] == '\0'))
954 ***************************************************************************
955 * Init color strings.
956 ***************************************************************************
958 void init_colors(void)
963 /* Read S_COLORS environment variable */
964 if (((e = getenv(ENV_COLORS)) == NULL) ||
965 !strcmp(e, C_NEVER) ||
966 (strcmp(e, C_ALWAYS) && !isatty(STDOUT_FILENO))) {
968 * Environment variable not set, or set to "never",
969 * or set to "auto" and stdout is not a terminal:
970 * Unset color strings.
972 strcpy(sc_percent_high, "");
973 strcpy(sc_percent_low, "");
974 strcpy(sc_zero_int_stat, "");
975 strcpy(sc_int_stat, "");
976 strcpy(sc_item_name, "");
977 strcpy(sc_sa_comment, "");
978 strcpy(sc_sa_restart, "");
979 strcpy(sc_normal, "");
984 /* Read S_COLORS_SGR environment variable */
985 if ((e = getenv(ENV_COLORS_SGR)) == NULL)
986 /* Environment variable not set */
989 for (p = strtok(e, ":"); p; p =strtok(NULL, ":")) {
992 if ((len > 7) || (len < 3) || (*(p + 1) != '=') ||
993 (strspn(p + 2, ";0123456789") != (len - 2)))
994 /* Ignore malformed codes */
999 snprintf(sc_percent_high, MAX_SGR_LEN, "\e[%sm", p + 2);
1002 snprintf(sc_percent_low, MAX_SGR_LEN, "\e[%sm", p + 2);
1005 snprintf(sc_zero_int_stat, MAX_SGR_LEN, "\e[%sm", p + 2);
1008 snprintf(sc_int_stat, MAX_SGR_LEN, "\e[%sm", p + 2);
1011 snprintf(sc_item_name, MAX_SGR_LEN, "\e[%sm", p + 2);
1014 snprintf(sc_sa_comment, MAX_SGR_LEN, "\e[%sm", p + 2);
1017 snprintf(sc_sa_restart, MAX_SGR_LEN, "\e[%sm", p + 2);
1024 ***************************************************************************
1025 * Print 64 bit unsigned values using colors.
1028 * @num Number of values to print.
1029 * @width Output width.
1030 ***************************************************************************
1032 void cprintf_u64(int num, int width, ...)
1038 va_start(args, width);
1040 for (i = 0; i < num; i++) {
1041 val = va_arg(args, unsigned long long);
1043 printf("%s", sc_zero_int_stat);
1046 printf("%s", sc_int_stat);
1048 printf(" %*"PRIu64, width, val);
1049 printf("%s", sc_normal);
1056 ***************************************************************************
1057 * Print hex values using colors.
1060 * @num Number of values to print.
1061 * @width Output width.
1062 ***************************************************************************
1064 void cprintf_x(int num, int width, ...)
1070 va_start(args, width);
1072 for (i = 0; i < num; i++) {
1073 val = va_arg(args, unsigned int);
1074 printf("%s", sc_int_stat);
1075 printf(" %*x", width, val);
1076 printf("%s", sc_normal);
1083 ***************************************************************************
1084 * Print "double" statistics values using colors.
1087 * @num Number of values to print.
1088 * @width Output width.
1089 * @wd Number of decimal places.
1090 ***************************************************************************
1092 void cprintf_f(int num, int wi, int wd, ...)
1100 for (i = 0; i < num; i++) {
1101 val = va_arg(args, double);
1102 if (((val < 0.005) && (val > -0.005)) ||
1103 ((wd == 0) && (val < 0.5))) {
1104 printf("%s", sc_zero_int_stat);
1107 printf("%s", sc_int_stat);
1109 printf(" %*.*f", wi, wd, val);
1110 printf("%s", sc_normal);
1117 ***************************************************************************
1118 * Print "percent" statistics values using colors.
1121 * @num Number of values to print.
1122 * @width Output width.
1123 * @wd Number of decimal places.
1124 ***************************************************************************
1126 void cprintf_pc(int num, int wi, int wd, ...)
1134 for (i = 0; i < num; i++) {
1135 val = va_arg(args, double);
1136 if (val >= PERCENT_LIMIT_HIGH) {
1137 printf("%s", sc_percent_high);
1139 else if (val >= PERCENT_LIMIT_LOW) {
1140 printf("%s", sc_percent_low);
1142 else if (val < 0.005) {
1143 printf("%s", sc_zero_int_stat);
1146 printf("%s", sc_int_stat);
1148 printf(" %*.*f", wi, wd, val);
1149 printf("%s", sc_normal);
1156 ***************************************************************************
1157 * Print item name using selected color.
1158 * Only one name can be displayed. Name can be an integer or a string.
1161 * @type 0 if name is an int, 1 if name is a string
1162 * @format Output format.
1163 * @item_string Item name (given as a string of characters).
1164 * @item_int Item name (given as an integer value).
1165 ***************************************************************************
1167 void cprintf_in(int type, char *format, char *item_string, int item_int)
1169 printf("%s", sc_item_name);
1171 printf(format, item_string);
1174 printf(format, item_int);
1176 printf("%s", sc_normal);
1180 ***************************************************************************
1181 * Print a string using selected color.
1184 * @type Type of string to display.
1185 * @format Output format.
1186 * @string String to display.
1187 ***************************************************************************
1189 void cprintf_s(int type, char *format, char *string)
1191 if (type == IS_STR) {
1192 printf("%s", sc_int_stat);
1194 else if (type == IS_ZERO) {
1195 printf("%s", sc_zero_int_stat);
1197 else if (type == IS_RESTART) {
1198 printf("%s", sc_sa_restart);
1202 printf("%s", sc_sa_comment);
1204 printf(format, string);
1205 printf("%s", sc_normal);