1  /*
       2   * lsirq - utility to display kernel interrupt information.
       3   *
       4   * Copyright (C) 2019 zhenwei pi <pizhenwei@bytedance.com>
       5   * Copyright (C) 2020 Karel Zak <kzak@redhat.com>
       6   *
       7   * This library is free software; you can redistribute it and/or
       8   * modify it under the terms of the GNU Lesser General Public
       9   * License as published by the Free Software Foundation; either
      10   * version 2.1 of the License, or (at your option) any later version.
      11   *
      12   * This library is distributed in the hope that it will be useful,
      13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15   * Lesser General Public License for more details.
      16   *
      17   * You should have received a copy of the GNU Lesser General Public
      18   * License along with this library; if not, write to the Free Software
      19   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
      20   */
      21  #include <ctype.h>
      22  #include <errno.h>
      23  #include <getopt.h>
      24  #include <limits.h>
      25  #include <locale.h>
      26  #include <stdio.h>
      27  #include <stdlib.h>
      28  #include <string.h>
      29  #include <sys/types.h>
      30  #include <unistd.h>
      31  
      32  #include <libsmartcols.h>
      33  
      34  #include "closestream.h"
      35  #include "optutils.h"
      36  #include "strutils.h"
      37  #include "xalloc.h"
      38  
      39  #include "irq-common.h"
      40  
      41  static int print_irq_data(struct irq_output *out, int softirq)
      42  {
      43  	struct libscols_table *table;
      44  
      45  	table = get_scols_table(out, NULL, NULL, softirq, 0, NULL);
      46  	if (!table)
      47  		return -1;
      48  
      49  	scols_print_table(table);
      50  	scols_unref_table(table);
      51  	return 0;
      52  }
      53  
      54  static void __attribute__((__noreturn__)) usage(void)
      55  {
      56  	fputs(USAGE_HEADER, stdout);
      57  	printf(_(" %s [options]\n"), program_invocation_short_name);
      58  	fputs(USAGE_SEPARATOR, stdout);
      59  
      60  	puts(_("Utility to display kernel interrupt information."));
      61  
      62  	fputs(USAGE_OPTIONS, stdout);
      63  	fputs(_(" -J, --json           use JSON output format\n"), stdout);
      64  	fputs(_(" -P, --pairs          use key=\"value\" output format\n"), stdout);
      65  	fputs(_(" -n, --noheadings     don't print headings\n"), stdout);
      66  	fputs(_(" -o, --output <list>  define which output columns to use\n"), stdout);
      67  	fputs(_(" -s, --sort <column>  specify sort column\n"), stdout);
      68  	fputs(_(" -S, --softirq        show softirqs instead of interrupts\n"), stdout);
      69  	fputs(USAGE_SEPARATOR, stdout);
      70  	printf(USAGE_HELP_OPTIONS(22));
      71  
      72  	fputs(USAGE_COLUMNS, stdout);
      73  	irq_print_columns(stdout, 1);
      74  
      75  	printf(USAGE_MAN_TAIL("lsirq(1)"));
      76  	exit(EXIT_SUCCESS);
      77  }
      78  
      79  int main(int argc, char **argv)
      80  {
      81  	struct irq_output out = {
      82  		.ncolumns = 0
      83  	};
      84  	static const struct option longopts[] = {
      85  		{"sort", required_argument, NULL, 's'},
      86  		{"noheadings", no_argument, NULL, 'n'},
      87  		{"output", required_argument, NULL, 'o'},
      88  		{"softirq", no_argument, NULL, 'S'},
      89  		{"json", no_argument, NULL, 'J'},
      90  		{"pairs", no_argument, NULL, 'P'},
      91  		{"help", no_argument, NULL, 'h'},
      92  		{"version", no_argument, NULL, 'V'},
      93  		{NULL, 0, NULL, 0}
      94  	};
      95  	int c;
      96  	const char *outarg = NULL;
      97  	static const ul_excl_t excl[] = {	/* rows and cols in ASCII order */
      98  		{'J', 'P'},
      99  		{0}
     100  	};
     101  	int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
     102  	int softirq = 0;
     103  
     104  	setlocale(LC_ALL, "");
     105  
     106  	while ((c = getopt_long(argc, argv, "no:s:ShJPV", longopts, NULL)) != -1) {
     107  		err_exclusive_options(c, longopts, excl, excl_st);
     108  
     109  		switch (c) {
     110  		case 'J':
     111  			out.json = 1;
     112  			break;
     113  		case 'P':
     114  			out.pairs = 1;
     115  			break;
     116  		case 'n':
     117  			out.no_headings = 1;
     118  			break;
     119  		case 'o':
     120  			outarg = optarg;
     121  			break;
     122  		case 's':
     123  			set_sort_func_by_name(&out, optarg);
     124  			break;
     125  		case 'S':
     126  			softirq = 1;
     127  			break;
     128  		case 'V':
     129  			print_version(EXIT_SUCCESS);
     130  		case 'h':
     131  			usage();
     132  		default:
     133  			errtryhelp(EXIT_FAILURE);
     134  		}
     135  	}
     136  
     137  	/* default */
     138  	if (!out.ncolumns) {
     139  		out.columns[out.ncolumns++] = COL_IRQ;
     140  		out.columns[out.ncolumns++] = COL_TOTAL;
     141  		out.columns[out.ncolumns++] = COL_NAME;
     142  	}
     143  
     144  	/* add -o [+]<list> to putput */
     145  	if (outarg && string_add_to_idarray(outarg, out.columns,
     146  				ARRAY_SIZE(out.columns),
     147  				&out.ncolumns,
     148  				irq_column_name_to_id) < 0)
     149  		exit(EXIT_FAILURE);
     150  
     151  	return print_irq_data(&out, softirq) == 0 ?  EXIT_SUCCESS : EXIT_FAILURE;
     152  }