Mercurial > hg > toybox
annotate toys/pending/sysctl.c @ 1282:c99912c6bc09 draft
First cleanup pass on sysctl.
Remove unnecessary typecasting of things that are already char * to char *,
and multiplying by sizeof(char *) which is 1. Rename do_process() do_flag_a()
since that's the only caller. Move read_key_values() down past trim_spaces()
and read_config_file() so it's next to its only two users. Replace some
euphemisms for 0 with 0.
replace_char() really sounds like something libc should already have one of,
but I'm blanking on it if so. (It doesn't need a temporary variable when the
argument variable is already a copy so changing it won't affect the caller.)
author | Rob Landley <rob@landley.net> |
---|---|
date | Mon, 12 May 2014 07:52:12 -0500 |
parents | 6b78ac1d7d58 |
children | 55de00e9daf4 |
rev | line source |
---|---|
1281 | 1 /* sysctl.c - A utility to read and manipulate the sysctl parameters. |
2 * | |
3 * Copyright 2014 Bilal Qureshi <bilal.jmi@gmail.com> | |
4 * Copyright 2014 Kyungwan Han <asura321@gmail.com> | |
5 * | |
6 * No Standard | |
7 | |
8 USE_SYSCTL(NEWTOY(sysctl, "^neNqwpaA[!ap][!aq][!aw][+aA]", TOYFLAG_USR|TOYFLAG_BIN)) | |
9 | |
10 config SYSCTL | |
11 bool "sysctl" | |
12 default n | |
13 help | |
14 usage: sysctl [OPTIONS] [KEY[=VALUE]]... | |
15 | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
16 Configure kernel parameters at runtime. |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
17 |
1281 | 18 -a, A Show all values |
19 -e Don't warn about unknown keys | |
20 -N Show only key names | |
21 -n Show only key values | |
22 -p FILE Set values from FILE (default /etc/sysctl.conf) | |
23 -q Set values silently | |
24 -w Set values | |
25 */ | |
26 #define FOR_sysctl | |
27 #include "toys.h" | |
28 | |
29 #define PROC_SYS_DIR "/proc/sys" | |
30 #define MAX_BYTES_LINE 1024 | |
31 | |
32 static void parse_key_name_value(char *param, char **key_name, char **key_value) | |
33 { | |
34 char *name, *value; | |
35 | |
36 if (!(name = strchr(param, '='))) goto show_error_msg; | |
37 value = name; | |
38 value++; | |
39 if (!(*value)) goto show_error_msg; | |
40 *name = '\0'; | |
41 *key_name = param; | |
42 *key_value = value; | |
43 return; | |
44 show_error_msg: | |
45 error_msg("error: '%s' must be of the form name=value", param); | |
46 } | |
47 | |
48 static void replace_char(char *str, char old, char new) | |
49 { | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
50 for (; *str; str++) if (*str == old) *str = new; |
1281 | 51 } |
52 | |
53 static void handle_file_error(char *key_name) | |
54 { | |
55 replace_char(key_name, '/', '.'); | |
56 if (errno == ENOENT) { | |
57 if (!(toys.optflags & FLAG_e)) | |
58 error_msg("error: '%s' is an unknown key", key_name); | |
59 else toys.exitval = 1; | |
60 } else perror_msg("error: %s key '%s'", (toys.optflags & FLAG_w) ? | |
61 "setting" : "reading", key_name); | |
62 } | |
63 | |
64 static void write_to_file(char *fpath, char *key_name, char *key_value) | |
65 { | |
66 int fd; | |
67 | |
68 replace_char(key_name, '.', '/'); | |
69 sprintf(toybuf, "%s/%s", fpath, key_name); | |
70 if ((fd = open(toybuf, O_WRONLY)) < 0) { | |
71 handle_file_error(key_name); | |
72 return; | |
73 } | |
74 xwrite(fd, key_value, strlen(key_value)); | |
75 xclose(fd); | |
76 if (!(toys.optflags & FLAG_q)) { | |
77 replace_char(key_name, '/', '.'); | |
78 if (toys.optflags & FLAG_N) xprintf("%s\n", key_name); | |
79 else if (toys.optflags & FLAG_n) xprintf("%s\n", key_value); | |
80 else xprintf("%s = %s\n", key_name, key_value); | |
81 } | |
82 } | |
83 | |
84 static char *get_key_value(char *buff, int *offset) | |
85 { | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
86 char *line, *tmp = buff + *offset; |
1281 | 87 int index = 0, multiplier = 1; |
88 | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
89 if (!*tmp) return 0; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
90 line = xmalloc(MAX_BYTES_LINE); |
1281 | 91 for (; *tmp != '\n'; tmp++) { |
92 line[index++] = *tmp; | |
93 if (MAX_BYTES_LINE == index) { // buffer overflow | |
94 multiplier++; | |
95 line = (char *) xrealloc(line, multiplier * MAX_BYTES_LINE); | |
96 } | |
97 } | |
98 line[index++] = '\0'; | |
99 *offset += index; | |
100 return line; | |
101 } | |
102 | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
103 static void trim_spaces(char **param) |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
104 { |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
105 int len = 0; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
106 char *str = *param, *p_start = str, *p_end; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
107 |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
108 if (p_start) { // start pointer to string |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
109 p_end = str + strlen(str) - 1; // end pointer to string |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
110 while (*p_start == ' ') p_start++; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
111 str = p_start; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
112 while (*p_end == ' ') p_end--; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
113 p_end++; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
114 *p_end = '\0'; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
115 len = (int) (p_end - str) + 1; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
116 memmove(*param, str, len); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
117 } |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
118 } |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
119 |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
120 // Read config file and write values to corresponding key name files |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
121 static void read_config_file(char *fname) |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
122 { |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
123 char *line, *name = NULL, *value = NULL; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
124 int fd = xopen(fname, O_RDONLY); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
125 |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
126 for (; (line = get_line(fd)); free(line), name = NULL, value = NULL) { |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
127 char *ptr = line; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
128 |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
129 while (*ptr == ' ' || *ptr == '\t') ptr++; |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
130 if (*ptr != '#' && *ptr != ';' && *ptr !='\n' && *ptr) { |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
131 parse_key_name_value(ptr, &name, &value); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
132 trim_spaces(&name); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
133 trim_spaces(&value); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
134 if (name && value) write_to_file(PROC_SYS_DIR, name, value); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
135 } |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
136 } |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
137 xclose(fd); |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
138 } |
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
139 |
1281 | 140 // Open file for each and every key name and read file contents |
141 void read_key_values(char *fpath) | |
142 { | |
143 char *key_value, *fdata, *key_name, *tmp = xstrdup(fpath); | |
144 int offset = 0; | |
145 | |
146 key_name = (tmp + strlen(PROC_SYS_DIR) + 1); | |
147 replace_char(key_name, '/', '.'); | |
148 if (!(fdata = readfile(fpath, NULL, 0))) { | |
149 handle_file_error(key_name); | |
150 free(tmp); | |
151 return; | |
152 } | |
153 if (toys.optflags & FLAG_N) { | |
154 xprintf("%s\n", key_name); | |
155 free(tmp); | |
156 free(fdata); | |
157 return; | |
158 } | |
159 for (; (key_value = get_key_value(fdata, &offset)); free(key_value)) { | |
160 if (!(toys.optflags & FLAG_q)) { | |
161 if (!(toys.optflags & FLAG_n)) xprintf("%s = ", key_name); | |
162 xprintf("%s\n", key_value); | |
163 } | |
164 } | |
165 free(tmp); | |
166 free(fdata); | |
167 } | |
168 | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
169 static int do_flag_a(struct dirtree *dt) |
1281 | 170 { |
171 char *fpath; | |
172 | |
173 if (!dirtree_notdotdot(dt)) return 0; // Skip . and .. | |
174 if (S_ISDIR(dt->st.st_mode)) return DIRTREE_RECURSE; | |
175 if ((fpath = dirtree_path(dt, 0))) { | |
176 read_key_values(fpath); | |
177 free(fpath); | |
178 } | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
179 |
1281 | 180 return 0; |
181 } | |
182 | |
183 void sysctl_main() | |
184 { | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
185 char *name = 0, *value = 0, **args = 0; |
1281 | 186 |
187 if (toys.optflags & FLAG_a) { | |
1282
c99912c6bc09
First cleanup pass on sysctl.
Rob Landley <rob@landley.net>
parents:
1281
diff
changeset
|
188 dirtree_read(PROC_SYS_DIR, do_flag_a); |
1281 | 189 return; |
190 } | |
191 if (toys.optflags & FLAG_p) { | |
192 if (*toys.optargs) read_config_file(*toys.optargs); | |
193 else read_config_file("/etc/sysctl.conf"); | |
194 return; | |
195 } | |
196 if (toys.optflags & FLAG_w) { | |
197 for (args = toys.optargs; *args; args++, name = NULL, value = NULL) { | |
198 parse_key_name_value(*args, &name, &value); | |
199 if (name && value) write_to_file(PROC_SYS_DIR, name, value); | |
200 } | |
201 return; | |
202 } | |
203 for (args = toys.optargs; *args; args++) { | |
204 replace_char(*args, '.', '/'); | |
205 sprintf(toybuf, "%s/%s", PROC_SYS_DIR, *args); | |
206 read_key_values(toybuf); | |
207 } | |
208 } |