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 #define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) 21 22 static int cmd_help(int argc, const char **argv); 23 24 /* Global cpu_info object available for all binaries 25 * Info only retrieved from CPU 0 26 * 27 * Values will be zero/unknown on non X86 archs 28 */ 29 struct cpupower_cpu_info cpupower_cpu_info; 30 int run_as_root; 31 /* Affected cpus chosen by -c/--cpu param */ 32 struct bitmask *cpus_chosen; 33 34 #ifdef DEBUG 35 int be_verbose; 36 #endif 37 38 static void print_help(void); 39 40 struct cmd_struct { 41 const char *cmd; 42 int (*main)(int, const char **); 43 int needs_root; 44 }; 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 { "idle-set", cmd_idle_set, 1 }, 51 { "set", cmd_set, 1 }, 52 { "info", cmd_info, 0 }, 53 { "monitor", cmd_monitor, 0 }, 54 { "help", cmd_help, 0 }, 55 /* { "bench", cmd_bench, 1 }, */ 56 }; 57 58 static void print_help(void) 59 { 60 unsigned int i; 61 62 #ifdef DEBUG 63 printf(_("Usage:\tcpupower [-d|--debug] [-c|--cpu cpulist ] <command> [<args>]\n")); 64 #else 65 printf(_("Usage:\tcpupower [-c|--cpu cpulist ] <command> [<args>]\n")); 66 #endif 67 printf(_("Supported commands are:\n")); 68 for (i = 0; i < ARRAY_SIZE(commands); i++) 69 printf("\t%s\n", commands[i].cmd); 70 printf(_("\nNot all commands can make use of the -c cpulist option.\n")); 71 printf(_("\nUse 'cpupower help <command>' for getting help for above commands.\n")); 72 } 73 74 static int print_man_page(const char *subpage) 75 { 76 int len; 77 char *page; 78 79 len = 10; /* enough for "cpupower-" */ 80 if (subpage != NULL) 81 len += strlen(subpage); 82 83 page = malloc(len); 84 if (!page) 85 return -ENOMEM; 86 87 sprintf(page, "cpupower"); 88 if ((subpage != NULL) && strcmp(subpage, "help")) { 89 strcat(page, "-"); 90 strcat(page, subpage); 91 } 92 93 execlp("man", "man", page, NULL); 94 95 /* should not be reached */ 96 return -EINVAL; 97 } 98 99 static int cmd_help(int argc, const char **argv) 100 { 101 if (argc > 1) { 102 print_man_page(argv[1]); /* exits within execlp() */ 103 return EXIT_FAILURE; 104 } 105 106 print_help(); 107 return EXIT_SUCCESS; 108 } 109 110 static void print_version(void) 111 { 112 printf(PACKAGE " " VERSION "\n"); 113 printf(_("Report errors and bugs to %s, please.\n"), PACKAGE_BUGREPORT); 114 } 115 116 static void handle_options(int *argc, const char ***argv) 117 { 118 int ret, x, new_argc = 0; 119 120 if (*argc < 1) 121 return; 122 123 for (x = 0; x < *argc && ((*argv)[x])[0] == '-'; x++) { 124 const char *param = (*argv)[x]; 125 if (!strcmp(param, "-h") || !strcmp(param, "--help")) { 126 print_help(); 127 exit(EXIT_SUCCESS); 128 } else if (!strcmp(param, "-c") || !strcmp(param, "--cpu")) { 129 if (*argc < 2) { 130 print_help(); 131 exit(EXIT_FAILURE); 132 } 133 if (!strcmp((*argv)[x+1], "all")) 134 bitmask_setall(cpus_chosen); 135 else { 136 ret = bitmask_parselist( 137 (*argv)[x+1], cpus_chosen); 138 if (ret < 0) { 139 fprintf(stderr, _("Error parsing cpu " 140 "list\n")); 141 exit(EXIT_FAILURE); 142 } 143 } 144 x += 1; 145 /* Cut out param: cpupower -c 1 info -> cpupower info */ 146 new_argc += 2; 147 continue; 148 } else if (!strcmp(param, "-v") || 149 !strcmp(param, "--version")) { 150 print_version(); 151 exit(EXIT_SUCCESS); 152 #ifdef DEBUG 153 } else if (!strcmp(param, "-d") || !strcmp(param, "--debug")) { 154 be_verbose = 1; 155 new_argc++; 156 continue; 157 #endif 158 } else { 159 fprintf(stderr, "Unknown option: %s\n", param); 160 print_help(); 161 exit(EXIT_FAILURE); 162 } 163 } 164 *argc -= new_argc; 165 *argv += new_argc; 166 } 167 168 int main(int argc, const char *argv[]) 169 { 170 const char *cmd; 171 unsigned int i, ret; 172 173 cpus_chosen = bitmask_alloc(sysconf(_SC_NPROCESSORS_CONF)); 174 175 argc--; 176 argv += 1; 177 178 handle_options(&argc, &argv); 179 180 cmd = argv[0]; 181 182 if (argc < 1) { 183 print_help(); 184 return EXIT_FAILURE; 185 } 186 187 setlocale(LC_ALL, ""); 188 textdomain(PACKAGE); 189 190 /* Turn "perf cmd --help" into "perf help cmd" */ 191 if (argc > 1 && !strcmp(argv[1], "--help")) { 192 argv[1] = argv[0]; 193 argv[0] = cmd = "help"; 194 } 195 196 get_cpu_info(0, &cpupower_cpu_info); 197 run_as_root = !getuid(); 198 199 for (i = 0; i < ARRAY_SIZE(commands); i++) { 200 struct cmd_struct *p = commands + i; 201 if (strcmp(p->cmd, cmd)) 202 continue; 203 if (!run_as_root && p->needs_root) { 204 fprintf(stderr, _("Subcommand %s needs root " 205 "privileges\n"), cmd); 206 return EXIT_FAILURE; 207 } 208 ret = p->main(argc, argv); 209 if (cpus_chosen) 210 bitmask_free(cpus_chosen); 211 return ret; 212 } 213 print_help(); 214 return EXIT_FAILURE; 215 } 216