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 #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 **); 23 int needs_root; 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 */ 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, 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 195 get_cpu_info(0, &cpupower_cpu_info); 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 } 215