Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
cpupower.c
Go to the documentation of this file.
1 /*
2  * (C) 2010,2011 Thomas Renninger <[email protected]>, Novell Inc.
3  *
4  * Licensed under the terms of the GNU GPL License version 2.
5  *
6  * Ideas taken over from the perf userspace tool (included in the Linus
7  * kernel git repo): subcommand builtins and param parsing.
8  */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <unistd.h>
14 #include <errno.h>
15 
16 #include "builtin.h"
17 #include "helpers/helpers.h"
18 #include "helpers/bitmask.h"
19 
20 struct cmd_struct {
21  const char *cmd;
22  int (*main)(int, const char **);
24 };
25 
26 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
27 
28 static int cmd_help(int argc, const char **argv);
29 
30 /* Global cpu_info object available for all binaries
31  * Info only retrieved from CPU 0
32  *
33  * Values will be zero/unknown on non X86 archs
34  */
37 /* Affected cpus chosen by -c/--cpu param */
39 
40 #ifdef DEBUG
41 int be_verbose;
42 #endif
43 
44 static void print_help(void);
45 
46 static struct cmd_struct commands[] = {
47  { "frequency-info", cmd_freq_info, 0 },
48  { "frequency-set", cmd_freq_set, 1 },
49  { "idle-info", cmd_idle_info, 0 },
50  { "set", cmd_set, 1 },
51  { "info", cmd_info, 0 },
52  { "monitor", cmd_monitor, 0 },
53  { "help", cmd_help, 0 },
54  /* { "bench", cmd_bench, 1 }, */
55 };
56 
57 static void print_help(void)
58 {
59  unsigned int i;
60 
61 #ifdef DEBUG
62  printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n"));
63 #else
64  printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n"));
65 #endif
66  printf(_("Supported commands are:\n"));
67  for (i = 0; i < ARRAY_SIZE(commands); i++)
68  printf("\t%s\n", commands[i].cmd);
69  printf(_("\nNot all commands can make use of the -c cpulist option.\n"));
70  printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n"));
71 }
72 
73 static int print_man_page(const char *subpage)
74 {
75  int len;
76  char *page;
77 
78  len = 10; /* enough for "cpupower-" */
79  if (subpage != NULL)
80  len += strlen(subpage);
81 
82  page = malloc(len);
83  if (!page)
84  return -ENOMEM;
85 
86  sprintf(page, "cpupower");
87  if ((subpage != NULL) && strcmp(subpage, "help")) {
88  strcat(page, "-");
89  strcat(page, subpage);
90  }
91 
92  execlp("man", "man", page, NULL);
93 
94  /* should not be reached */
95  return -EINVAL;
96 }
97 
98 static int cmd_help(int argc, const char **argv)
99 {
100  if (argc > 1) {
101  print_man_page(argv[1]); /* exits within execlp() */
102  return EXIT_FAILURE;
103  }
104 
105  print_help();
106  return EXIT_SUCCESS;
107 }
108 
109 static void print_version(void)
110 {
111  printf(PACKAGE " " VERSION "\n");
112  printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
113 }
114 
115 static void handle_options(int *argc, const char ***argv)
116 {
117  int ret, x, new_argc = 0;
118 
119  if (*argc < 1)
120  return;
121 
122  for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) {
123  const char *param = (*argv)[x];
124  if (!strcmp(param, "-h") || !strcmp(param, "--help")) {
125  print_help();
126  exit(EXIT_SUCCESS);
127  } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) {
128  if (*argc < 2) {
129  print_help();
130  exit(EXIT_FAILURE);
131  }
132  if (!strcmp((*argv)[x+1], "all"))
133  bitmask_setall(cpus_chosen);
134  else {
135  ret = bitmask_parselist(
136  (*argv)[x+1], cpus_chosen);
137  if (ret < 0) {
138  fprintf(stderr, _("Error parsing cpu "
139  "list\n"));
140  exit(EXIT_FAILURE);
141  }
142  }
143  x += 1;
144  /* Cut out param: cpupower -c 1 info -> cpupower info */
145  new_argc += 2;
146  continue;
147  } else if (!strcmp(param, "-v") ||
148  !strcmp(param, "--version")) {
149  print_version();
150  exit(EXIT_SUCCESS);
151 #ifdef DEBUG
152  } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) {
153  be_verbose = 1;
154  new_argc++;
155  continue;
156 #endif
157  } else {
158  fprintf(stderr, "Unknown option: %s\n", param);
159  print_help();
160  exit(EXIT_FAILURE);
161  }
162  }
163  *argc -= new_argc;
164  *argv += new_argc;
165 }
166 
167 int main(int argc, const char *argv[])
168 {
169  const char *cmd;
170  unsigned int i, ret;
171 
172  cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
173 
174  argc--;
175  argv += 1;
176 
177  handle_options(&argc, &argv);
178 
179  cmd = argv[0];
180 
181  if (argc < 1) {
182  print_help();
183  return EXIT_FAILURE;
184  }
185 
186  setlocale(LC_ALL, "");
187  textdomain(PACKAGE);
188 
189  /* Turn "perf cmd --help" into "perf help cmd" */
190  if (argc > 1 && !strcmp(argv[1], "--help")) {
191  argv[1] = argv[0];
192  argv[0] = cmd = "help";
193  }
194 
196  run_as_root = !getuid();
197 
198  for (i = 0; i < ARRAY_SIZE(commands); i++) {
199  struct cmd_struct *p = commands + i;
200  if (strcmp(p->cmd, cmd))
201  continue;
202  if (!run_as_root && p->needs_root) {
203  fprintf(stderr, _("Subcommand %s needs root "
204  "privileges\n"), cmd);
205  return EXIT_FAILURE;
206  }
207  ret = p->main(argc, argv);
208  if (cpus_chosen)
209  bitmask_free(cpus_chosen);
210  return ret;
211  }
212  print_help();
213  return EXIT_FAILURE;
214 }