b048e559535995f489f54d8ee5d42ff94939d7c7
[linux-2.6.git] / tools / power / cpupower / utils / cpupower.c
1 /*
2  *  (C) 2010,2011       Thomas Renninger <trenn@suse.de>, 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
15 #include "builtin.h"
16 #include "helpers/helpers.h"
17 #include "helpers/bitmask.h"
18
19 struct cmd_struct {
20         const char *cmd;
21         int (*main)(int, const char **);
22         void (*usage)(void);
23         int needs_root;
24 };
25
26 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
27
28 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  */
35 struct cpupower_cpu_info cpupower_cpu_info;
36 int run_as_root;
37 /* Affected cpus chosen by -c/--cpu param */
38 struct bitmask *cpus_chosen;
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,  freq_info_help, 0       },
48         { "frequency-set",      cmd_freq_set,   freq_set_help,  1       },
49         { "idle-info",          cmd_idle_info,  idle_info_help, 0       },
50         { "set",                cmd_set,        set_help,       1       },
51         { "info",               cmd_info,       info_help,      0       },
52         { "monitor",            cmd_monitor,    monitor_help,   0       },
53         { "help",               cmd_help,       print_help,             0       },
54         //      { "bench",      cmd_bench,      NULL,           1       },
55 };
56
57 int cmd_help(int argc, const char **argv)
58 {
59         unsigned int i;
60
61         if (argc > 1) {
62                 for (i = 0; i < ARRAY_SIZE(commands); i++) {
63                         struct cmd_struct *p = commands + i;
64                         if (strcmp(p->cmd, argv[1]))
65                                 continue;
66                         if (p->usage) {
67                                 p->usage();
68                                 return EXIT_SUCCESS;
69                         }
70                 }
71         }
72         print_help();
73         if (argc == 1)
74                 return EXIT_SUCCESS; /* cpupower help */
75         return EXIT_FAILURE;
76 }
77
78 static void print_help(void)
79 {
80         unsigned int i;
81
82 #ifdef DEBUG
83         printf(_("cpupower [ -d ][ -c cpulist ] subcommand [ARGS]\n"));
84         printf(_("  -d, --debug      May increase output (stderr) on some subcommands\n"));
85 #else
86         printf(_("cpupower [ -c cpulist ] subcommand [ARGS]\n"));
87 #endif
88         printf(_("cpupower --version\n"));
89         printf(_("Supported subcommands are:\n"));
90         for (i = 0; i < ARRAY_SIZE(commands); i++)
91                 printf("\t%s\n", commands[i].cmd);
92         printf(_("\nSome subcommands can make use of the -c cpulist option.\n"));
93         printf(_("Look at the general cpupower manpage how to use it\n"));
94         printf(_("and read up the subcommand's manpage whether it is supported.\n"));
95         printf(_("\nUse cpupower help subcommand for getting help for above subcommands.\n"));
96 }
97
98 static void print_version(void) {
99         printf(PACKAGE " " VERSION "\n");
100         printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT);
101 }
102
103 static void handle_options(int *argc, const char ***argv)
104 {
105         int ret, x, new_argc = 0;
106
107         if (*argc < 1)
108                 return;
109
110         for (x = 0;  x < *argc && ((*argv)[x])[0] == '-'; x++) {
111                 const char *param = (*argv)[x];
112                 if (!strcmp(param, "-h") || !strcmp(param, "--help")){
113                         print_help();
114                         exit(EXIT_SUCCESS);
115                 } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")){
116                         if (*argc < 2) {
117                                 print_help();
118                                 exit(EXIT_FAILURE);
119                         }
120                         if (!strcmp((*argv)[x+1], "all"))
121                                 bitmask_setall(cpus_chosen);
122                         else {
123                                 ret = bitmask_parselist(
124                                                 (*argv)[x+1], cpus_chosen);
125                                 if (ret < 0) {
126                                         fprintf(stderr, _("Error parsing cpu "
127                                                           "list\n"));
128                                         exit(EXIT_FAILURE);
129                                 }
130                         }
131                         x += 1;
132                         /* Cut out param: cpupower -c 1 info -> cpupower info */
133                         new_argc += 2;
134                         continue;
135                 } else if (!strcmp(param, "-v") || !strcmp(param, "--version")){
136                         print_version();
137                         exit(EXIT_SUCCESS);
138 #ifdef DEBUG
139                 } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")){
140                         be_verbose = 1;
141                         new_argc ++;
142                         continue;
143 #endif
144                 } else {
145                         fprintf(stderr, "Unknown option: %s\n", param);
146                         print_help();
147                         exit(EXIT_FAILURE);
148                 }
149         }
150         *argc -= new_argc;
151         *argv += new_argc;
152 }
153
154 int main(int argc, const char *argv[])
155 {
156         const char *cmd;
157         unsigned int i, ret;
158
159         cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF));
160
161         argc--;
162         argv += 1;
163
164         handle_options(&argc, &argv);
165
166         cmd = argv[0];
167
168         if (argc < 1) {
169                 print_help();
170                 return EXIT_FAILURE;
171         }
172
173         setlocale(LC_ALL, "");
174         textdomain (PACKAGE);
175
176         /* Turn "perf cmd --help" into "perf help cmd" */
177         if (argc > 1 && !strcmp(argv[1], "--help")) {
178                 argv[1] = argv[0];
179                 argv[0] = cmd = "help";
180         }
181
182         get_cpu_info(0, &cpupower_cpu_info);
183         run_as_root = !getuid();
184
185         for (i = 0; i < ARRAY_SIZE(commands); i++) {
186                 struct cmd_struct *p = commands + i;
187                 if (strcmp(p->cmd, cmd))
188                         continue;
189                 if (!run_as_root && p->needs_root) {
190                         fprintf(stderr, _("Subcommand %s needs root "
191                                           "privileges\n"), cmd);
192                         return EXIT_FAILURE;
193                 }
194                 ret = p->main(argc, argv);
195                 if (cpus_chosen)
196                         bitmask_free(cpus_chosen);
197                 return ret;
198         }
199         print_help();
200         return EXIT_FAILURE;
201 }