10f66f451Sopenharmony_ci/* sysctl.c - A utility to read and manipulate the sysctl parameters. 20f66f451Sopenharmony_ci * 30f66f451Sopenharmony_ci * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com> 40f66f451Sopenharmony_ci * Copyright 2014 Kyungwan Han <asura321@gmail.com> 50f66f451Sopenharmony_ci * 60f66f451Sopenharmony_ci * No Standard 70f66f451Sopenharmony_ci 80f66f451Sopenharmony_ciUSE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_SBIN)) 90f66f451Sopenharmony_ci 100f66f451Sopenharmony_ciconfig SYSCTL 110f66f451Sopenharmony_ci bool "sysctl" 120f66f451Sopenharmony_ci default y 130f66f451Sopenharmony_ci help 140f66f451Sopenharmony_ci usage: sysctl [-aAeNnqw] [-p [FILE] | KEY[=VALUE]...] 150f66f451Sopenharmony_ci 160f66f451Sopenharmony_ci Read/write system control data (under /proc/sys). 170f66f451Sopenharmony_ci 180f66f451Sopenharmony_ci -a,A Show all values 190f66f451Sopenharmony_ci -e Don't warn about unknown keys 200f66f451Sopenharmony_ci -N Don't print key values 210f66f451Sopenharmony_ci -n Don't print key names 220f66f451Sopenharmony_ci -p Read values from FILE (default /etc/sysctl.conf) 230f66f451Sopenharmony_ci -q Don't show value after write 240f66f451Sopenharmony_ci -w Only write values (object to reading) 250f66f451Sopenharmony_ci*/ 260f66f451Sopenharmony_ci#define FOR_sysctl 270f66f451Sopenharmony_ci#include "toys.h" 280f66f451Sopenharmony_ci 290f66f451Sopenharmony_ci// Null terminate at =, return value 300f66f451Sopenharmony_cistatic char *split_key(char *key) 310f66f451Sopenharmony_ci{ 320f66f451Sopenharmony_ci char *value = strchr(key, '='); 330f66f451Sopenharmony_ci 340f66f451Sopenharmony_ci if (value) *(value++)=0; 350f66f451Sopenharmony_ci 360f66f451Sopenharmony_ci return value; 370f66f451Sopenharmony_ci} 380f66f451Sopenharmony_ci 390f66f451Sopenharmony_cistatic void replace_char(char *str, char old, char new) 400f66f451Sopenharmony_ci{ 410f66f451Sopenharmony_ci for (; *str; str++) if (*str == old) *str = new; 420f66f451Sopenharmony_ci} 430f66f451Sopenharmony_ci 440f66f451Sopenharmony_cistatic void key_error(char *key) 450f66f451Sopenharmony_ci{ 460f66f451Sopenharmony_ci if (errno == ENOENT) { 470f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_e)) error_msg("unknown key '%s'", key); 480f66f451Sopenharmony_ci } else perror_msg("key '%s'", key); 490f66f451Sopenharmony_ci} 500f66f451Sopenharmony_ci 510f66f451Sopenharmony_cistatic int write_key(char *path, char *key, char *value) 520f66f451Sopenharmony_ci{ 530f66f451Sopenharmony_ci int fd = open(path, O_WRONLY); 540f66f451Sopenharmony_ci 550f66f451Sopenharmony_ci if (fd < 0) { 560f66f451Sopenharmony_ci key_error(key); 570f66f451Sopenharmony_ci 580f66f451Sopenharmony_ci return 0; 590f66f451Sopenharmony_ci } 600f66f451Sopenharmony_ci xwrite(fd, value, strlen(value)); 610f66f451Sopenharmony_ci xclose(fd); 620f66f451Sopenharmony_ci 630f66f451Sopenharmony_ci return 1; 640f66f451Sopenharmony_ci} 650f66f451Sopenharmony_ci 660f66f451Sopenharmony_ci// Display all keys under a path 670f66f451Sopenharmony_cistatic int do_show_keys(struct dirtree *dt) 680f66f451Sopenharmony_ci{ 690f66f451Sopenharmony_ci char *path, *data, *key; 700f66f451Sopenharmony_ci 710f66f451Sopenharmony_ci if (!dirtree_notdotdot(dt)) return 0; // Skip . and .. 720f66f451Sopenharmony_ci if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE; 730f66f451Sopenharmony_ci 740f66f451Sopenharmony_ci path = dirtree_path(dt, 0); 750f66f451Sopenharmony_ci data = readfile(path, 0, 0); 760f66f451Sopenharmony_ci replace_char(key = path + 10, '/', '.'); // skip "/proc/sys/" 770f66f451Sopenharmony_ci if (!data) key_error(key); 780f66f451Sopenharmony_ci else { 790f66f451Sopenharmony_ci // Print the parts that aren't switched off by flags. 800f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_n)) xprintf("%s", key); 810f66f451Sopenharmony_ci if (!(toys.optflags & (FLAG_N|FLAG_n))) xprintf(" = "); 820f66f451Sopenharmony_ci for (key = data+strlen(data); key > data && isspace(*--key); *key = 0); 830f66f451Sopenharmony_ci if (!(toys.optflags & FLAG_N)) xprintf("%s", data); 840f66f451Sopenharmony_ci if ((toys.optflags & (FLAG_N|FLAG_n)) != (FLAG_N|FLAG_n)) xputc('\n'); 850f66f451Sopenharmony_ci } 860f66f451Sopenharmony_ci 870f66f451Sopenharmony_ci free(data); 880f66f451Sopenharmony_ci free(path); 890f66f451Sopenharmony_ci 900f66f451Sopenharmony_ci return 0; 910f66f451Sopenharmony_ci} 920f66f451Sopenharmony_ci 930f66f451Sopenharmony_ci// Read/write entries under a key. Accepts "key=value" in key if !value 940f66f451Sopenharmony_cistatic void process_key(char *key, char *value) 950f66f451Sopenharmony_ci{ 960f66f451Sopenharmony_ci char *path; 970f66f451Sopenharmony_ci 980f66f451Sopenharmony_ci if (!value) value = split_key(key); 990f66f451Sopenharmony_ci if ((toys.optflags & FLAG_w) && !value) { 1000f66f451Sopenharmony_ci error_msg("'%s' not key=value", key); 1010f66f451Sopenharmony_ci 1020f66f451Sopenharmony_ci return; 1030f66f451Sopenharmony_ci } 1040f66f451Sopenharmony_ci 1050f66f451Sopenharmony_ci path = xmprintf("/proc/sys/%s", key); 1060f66f451Sopenharmony_ci replace_char(path, '.', '/'); 1070f66f451Sopenharmony_ci // Note: failure to assign to a non-leaf node suppresses the display. 1080f66f451Sopenharmony_ci if (!(value && (!write_key(path, key, value) || (toys.optflags & FLAG_q)))) { 1090f66f451Sopenharmony_ci if (!access(path, R_OK)) dirtree_read(path, do_show_keys); 1100f66f451Sopenharmony_ci else key_error(key); 1110f66f451Sopenharmony_ci } 1120f66f451Sopenharmony_ci free(path); 1130f66f451Sopenharmony_ci} 1140f66f451Sopenharmony_ci 1150f66f451Sopenharmony_civoid sysctl_main() 1160f66f451Sopenharmony_ci{ 1170f66f451Sopenharmony_ci char **args = 0; 1180f66f451Sopenharmony_ci 1190f66f451Sopenharmony_ci // Display all keys 1200f66f451Sopenharmony_ci if (toys.optflags & FLAG_a) dirtree_read("/proc/sys", do_show_keys); 1210f66f451Sopenharmony_ci 1220f66f451Sopenharmony_ci // read file 1230f66f451Sopenharmony_ci else if (toys.optflags & FLAG_p) { 1240f66f451Sopenharmony_ci FILE *fp = xfopen(*toys.optargs ? *toys.optargs : "/etc/sysctl.conf", "r"); 1250f66f451Sopenharmony_ci size_t len; 1260f66f451Sopenharmony_ci 1270f66f451Sopenharmony_ci for (;;) { 1280f66f451Sopenharmony_ci char *line = 0, *key, *val; 1290f66f451Sopenharmony_ci 1300f66f451Sopenharmony_ci if (-1 == (len = getline(&line, &len, fp))) break; 1310f66f451Sopenharmony_ci key = line; 1320f66f451Sopenharmony_ci while (isspace(*key)) key++; 1330f66f451Sopenharmony_ci if (*key == '#' || *key == ';' || !*key) continue; 1340f66f451Sopenharmony_ci while (len && isspace(line[len-1])) line[--len] = 0; 1350f66f451Sopenharmony_ci if (!(val = split_key(line))) { 1360f66f451Sopenharmony_ci error_msg("'%s' not key=value", line); 1370f66f451Sopenharmony_ci continue; 1380f66f451Sopenharmony_ci } 1390f66f451Sopenharmony_ci 1400f66f451Sopenharmony_ci // Trim whitespace around = 1410f66f451Sopenharmony_ci len = (val-line)-1; 1420f66f451Sopenharmony_ci while (len && isspace(line[len-1])) line[--len] = 0; 1430f66f451Sopenharmony_ci while (isspace(*val)) val++;; 1440f66f451Sopenharmony_ci 1450f66f451Sopenharmony_ci process_key(key, val); 1460f66f451Sopenharmony_ci free(line); 1470f66f451Sopenharmony_ci } 1480f66f451Sopenharmony_ci fclose(fp); 1490f66f451Sopenharmony_ci 1500f66f451Sopenharmony_ci // Loop through arguments, displaying or assigning as appropriate 1510f66f451Sopenharmony_ci } else { 1520f66f451Sopenharmony_ci if (!*toys.optargs) help_exit("Needs 1 arg"); 1530f66f451Sopenharmony_ci for (args = toys.optargs; *args; args++) process_key(*args, 0); 1540f66f451Sopenharmony_ci } 1550f66f451Sopenharmony_ci} 156