1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * builtin-config.c 4 * 5 * Copyright (C) 2015, Taeung Song <treeze.taeung@gmail.com> 6 * 7 */ 8 #include "builtin.h" 9 10 #include "perf.h" 11 12 #include "util/cache.h" 13 #include <subcmd/parse-options.h> 14 #include "util/util.h" 15 #include "util/debug.h" 16 #include "util/config.h" 17 #include <linux/string.h> 18 19 static bool use_system_config, use_user_config; 20 21 static const char * const config_usage[] = { 22 "perf config [<file-option>] [options] [section.name[=value] ...]", 23 NULL 24 }; 25 26 enum actions { 27 ACTION_LIST = 1 28 } actions; 29 30 static struct option config_options[] = { 31 OPT_SET_UINT('l', "list", &actions, 32 "show current config variables", ACTION_LIST), 33 OPT_BOOLEAN(0, "system", &use_system_config, "use system config file"), 34 OPT_BOOLEAN(0, "user", &use_user_config, "use user config file"), 35 OPT_END() 36 }; 37 38 static int set_config(struct perf_config_set *set, const char *file_name, 39 const char *var, const char *value) 40 { 41 struct perf_config_section *section = NULL; 42 struct perf_config_item *item = NULL; 43 const char *first_line = "# this file is auto-generated."; 44 FILE *fp; 45 46 if (set == NULL) 47 return -1; 48 49 fp = fopen(file_name, "w"); 50 if (!fp) 51 return -1; 52 53 perf_config_set__collect(set, file_name, var, value); 54 fprintf(fp, "%s\n", first_line); 55 56 /* overwrite configvariables */ 57 perf_config_items__for_each_entry(&set->sections, section) { 58 if (!use_system_config && section->from_system_config) 59 continue; 60 fprintf(fp, "[%s]\n", section->name); 61 62 perf_config_items__for_each_entry(§ion->items, item) { 63 if (!use_system_config && item->from_system_config) 64 continue; 65 if (item->value) 66 fprintf(fp, "\t%s = %s\n", 67 item->name, item->value); 68 } 69 } 70 fclose(fp); 71 72 return 0; 73 } 74 75 static int show_spec_config(struct perf_config_set *set, const char *var) 76 { 77 struct perf_config_section *section; 78 struct perf_config_item *item; 79 80 if (set == NULL) 81 return -1; 82 83 perf_config_items__for_each_entry(&set->sections, section) { 84 if (!strstarts(var, section->name)) 85 continue; 86 87 perf_config_items__for_each_entry(§ion->items, item) { 88 const char *name = var + strlen(section->name) + 1; 89 90 if (strcmp(name, item->name) == 0) { 91 char *value = item->value; 92 93 if (value) { 94 printf("%s=%s\n", var, value); 95 return 0; 96 } 97 } 98 99 } 100 } 101 102 return 0; 103 } 104 105 static int show_config(struct perf_config_set *set) 106 { 107 struct perf_config_section *section; 108 struct perf_config_item *item; 109 110 if (set == NULL) 111 return -1; 112 113 perf_config_set__for_each_entry(set, section, item) { 114 char *value = item->value; 115 116 if (value) 117 printf("%s.%s=%s\n", section->name, 118 item->name, value); 119 } 120 121 return 0; 122 } 123 124 static int parse_config_arg(char *arg, char **var, char **value) 125 { 126 const char *last_dot = strchr(arg, '.'); 127 128 /* 129 * Since "var" actually contains the section name and the real 130 * config variable name separated by a dot, we have to know where the dot is. 131 */ 132 if (last_dot == NULL || last_dot == arg) { 133 pr_err("The config variable does not contain a section name: %s\n", arg); 134 return -1; 135 } 136 if (!last_dot[1]) { 137 pr_err("The config variable does not contain a variable name: %s\n", arg); 138 return -1; 139 } 140 141 *value = strchr(arg, '='); 142 if (*value == NULL) 143 *var = arg; 144 else if (!strcmp(*value, "=")) { 145 pr_err("The config variable does not contain a value: %s\n", arg); 146 return -1; 147 } else { 148 *value = *value + 1; /* excluding a first character '=' */ 149 *var = strsep(&arg, "="); 150 if (*var[0] == '\0') { 151 pr_err("invalid config variable: %s\n", arg); 152 return -1; 153 } 154 } 155 156 return 0; 157 } 158 159 int cmd_config(int argc, const char **argv) 160 { 161 int i, ret = -1; 162 struct perf_config_set *set; 163 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 164 const char *config_filename; 165 166 argc = parse_options(argc, argv, config_options, config_usage, 167 PARSE_OPT_STOP_AT_NON_OPTION); 168 169 if (use_system_config && use_user_config) { 170 pr_err("Error: only one config file at a time\n"); 171 parse_options_usage(config_usage, config_options, "user", 0); 172 parse_options_usage(NULL, config_options, "system", 0); 173 return -1; 174 } 175 176 if (use_system_config) 177 config_exclusive_filename = perf_etc_perfconfig(); 178 else if (use_user_config) 179 config_exclusive_filename = user_config; 180 181 if (!config_exclusive_filename) 182 config_filename = user_config; 183 else 184 config_filename = config_exclusive_filename; 185 186 /* 187 * At only 'config' sub-command, individually use the config set 188 * because of reinitializing with options config file location. 189 */ 190 set = perf_config_set__new(); 191 if (!set) 192 goto out_err; 193 194 switch (actions) { 195 case ACTION_LIST: 196 if (argc) { 197 pr_err("Error: takes no arguments\n"); 198 parse_options_usage(config_usage, config_options, "l", 1); 199 } else { 200 if (show_config(set) < 0) { 201 pr_err("Nothing configured, " 202 "please check your %s \n", config_filename); 203 goto out_err; 204 } 205 } 206 break; 207 default: 208 if (!argc) { 209 usage_with_options(config_usage, config_options); 210 break; 211 } 212 213 for (i = 0; argv[i]; i++) { 214 char *var, *value; 215 char *arg = strdup(argv[i]); 216 217 if (!arg) { 218 pr_err("%s: strdup failed\n", __func__); 219 goto out_err; 220 } 221 222 if (parse_config_arg(arg, &var, &value) < 0) { 223 free(arg); 224 goto out_err; 225 } 226 227 if (value == NULL) { 228 if (show_spec_config(set, var) < 0) { 229 pr_err("%s is not configured: %s\n", 230 var, config_filename); 231 free(arg); 232 goto out_err; 233 } 234 } else { 235 if (set_config(set, config_filename, var, value) < 0) { 236 pr_err("Failed to set '%s=%s' on %s\n", 237 var, value, config_filename); 238 free(arg); 239 goto out_err; 240 } 241 } 242 free(arg); 243 } 244 } 245 246 ret = 0; 247 out_err: 248 perf_config_set__delete(set); 249 return ret; 250 } 251